Linux-libre 5.3.12-gnu
[librecmc/linux-libre.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         if [ "$1" = "xzonly" ]; then
157                 fwfile="${FW}-orig"
158         else
159                 fwfile="$FW"
160         fi
161         for i in $(seq 0 3); do
162                 config_set_read_fw_idx $i
163                 # Verify the contents are what we expect.
164                 # -Z required for now -- check for yourself, md5sum
165                 # on $FW and DIR/read_firmware will yield the same. Even
166                 # cmp agrees, so something is off.
167                 if ! diff -q -Z "$fwfile" $DIR/read_firmware 2>/dev/null ; then
168                         echo "request #$i: firmware was not loaded" >&2
169                         exit 1
170                 fi
171         done
172 }
173
174 read_firmwares_expect_nofile()
175 {
176         for i in $(seq 0 3); do
177                 config_set_read_fw_idx $i
178                 # Ensures contents differ
179                 if diff -q -Z "$FW" $DIR/read_firmware 2>/dev/null ; then
180                         echo "request $i: file was not expected to match" >&2
181                         exit 1
182                 fi
183         done
184 }
185
186 test_batched_request_firmware_nofile()
187 {
188         echo -n "Batched request_firmware() nofile try #$1: "
189         config_reset
190         config_set_name nope-test-firmware.bin
191         config_trigger_sync
192         read_firmwares_expect_nofile
193         release_all_firmware
194         echo "OK"
195 }
196
197 test_batched_request_firmware_direct_nofile()
198 {
199         echo -n "Batched request_firmware_direct() nofile try #$1: "
200         config_reset
201         config_set_name nope-test-firmware.bin
202         config_set_sync_direct
203         config_trigger_sync
204         release_all_firmware
205         echo "OK"
206 }
207
208 test_request_firmware_nowait_uevent_nofile()
209 {
210         echo -n "Batched request_firmware_nowait(uevent=true) nofile try #$1: "
211         config_reset
212         config_set_name nope-test-firmware.bin
213         config_trigger_async
214         release_all_firmware
215         echo "OK"
216 }
217
218 test_wait_and_cancel_custom_load()
219 {
220         if [ "$HAS_FW_LOADER_USER_HELPER" != "yes" ]; then
221                 return
222         fi
223         local timeout=10
224         name=$1
225         while [ ! -e "$DIR"/"$name"/loading ]; do
226                 sleep 0.1
227                 timeout=$(( $timeout - 1 ))
228                 if [ "$timeout" -eq 0 ]; then
229                         echo "firmware interface never appeared:" >&2
230                         echo "$DIR/$name/loading" >&2
231                         exit 1
232                 fi
233         done
234         echo -1 >"$DIR"/"$name"/loading
235 }
236
237 test_request_firmware_nowait_custom_nofile()
238 {
239         echo -n "Batched request_firmware_nowait(uevent=false) nofile try #$1: "
240         config_reset
241         config_unset_uevent
242         RANDOM_FILE_PATH=$(setup_random_file_fake)
243         RANDOM_FILE="$(basename $RANDOM_FILE_PATH)"
244         config_set_name $RANDOM_FILE
245         config_trigger_async &
246         test_wait_and_cancel_custom_load $RANDOM_FILE
247         wait
248         release_all_firmware
249         echo "OK"
250 }
251
252 test_batched_request_firmware()
253 {
254         echo -n "Batched request_firmware() $2 try #$1: "
255         config_reset
256         config_trigger_sync
257         read_firmwares $2
258         release_all_firmware
259         echo "OK"
260 }
261
262 test_batched_request_firmware_direct()
263 {
264         echo -n "Batched request_firmware_direct() $2 try #$1: "
265         config_reset
266         config_set_sync_direct
267         config_trigger_sync
268         release_all_firmware
269         echo "OK"
270 }
271
272 test_request_firmware_nowait_uevent()
273 {
274         echo -n "Batched request_firmware_nowait(uevent=true) $2 try #$1: "
275         config_reset
276         config_trigger_async
277         release_all_firmware
278         echo "OK"
279 }
280
281 test_request_firmware_nowait_custom()
282 {
283         echo -n "Batched request_firmware_nowait(uevent=false) $2 try #$1: "
284         config_reset
285         config_unset_uevent
286         RANDOM_FILE_PATH=$(setup_random_file)
287         RANDOM_FILE="$(basename $RANDOM_FILE_PATH)"
288         if [ "$2" = "both" ]; then
289                 xz -9 -C crc32 -k $RANDOM_FILE_PATH
290         elif [ "$2" = "xzonly" ]; then
291                 xz -9 -C crc32 $RANDOM_FILE_PATH
292         fi
293         config_set_name $RANDOM_FILE
294         config_trigger_async
295         release_all_firmware
296         echo "OK"
297 }
298
299 # Only continue if batched request triggers are present on the
300 # test-firmware driver
301 test_config_present
302
303 # test with the file present
304 echo
305 echo "Testing with the file present..."
306 for i in $(seq 1 5); do
307         test_batched_request_firmware $i normal
308 done
309
310 for i in $(seq 1 5); do
311         test_batched_request_firmware_direct $i normal
312 done
313
314 for i in $(seq 1 5); do
315         test_request_firmware_nowait_uevent $i normal
316 done
317
318 for i in $(seq 1 5); do
319         test_request_firmware_nowait_custom $i normal
320 done
321
322 # Test for file not found, errors are expected, the failure would be
323 # a hung task, which would require a hard reset.
324 echo
325 echo "Testing with the file missing..."
326 for i in $(seq 1 5); do
327         test_batched_request_firmware_nofile $i
328 done
329
330 for i in $(seq 1 5); do
331         test_batched_request_firmware_direct_nofile $i
332 done
333
334 for i in $(seq 1 5); do
335         test_request_firmware_nowait_uevent_nofile $i
336 done
337
338 for i in $(seq 1 5); do
339         test_request_firmware_nowait_custom_nofile $i
340 done
341
342 test "$HAS_FW_LOADER_COMPRESS" != "yes" && exit 0
343
344 # test with both files present
345 xz -9 -C crc32 -k $FW
346 config_set_name $NAME
347 echo
348 echo "Testing with both plain and xz files present..."
349 for i in $(seq 1 5); do
350         test_batched_request_firmware $i both
351 done
352
353 for i in $(seq 1 5); do
354         test_batched_request_firmware_direct $i both
355 done
356
357 for i in $(seq 1 5); do
358         test_request_firmware_nowait_uevent $i both
359 done
360
361 for i in $(seq 1 5); do
362         test_request_firmware_nowait_custom $i both
363 done
364
365 # test with only xz file present
366 mv "$FW" "${FW}-orig"
367 echo
368 echo "Testing with only xz file present..."
369 for i in $(seq 1 5); do
370         test_batched_request_firmware $i xzonly
371 done
372
373 for i in $(seq 1 5); do
374         test_batched_request_firmware_direct $i xzonly
375 done
376
377 for i in $(seq 1 5); do
378         test_request_firmware_nowait_uevent $i xzonly
379 done
380
381 for i in $(seq 1 5); do
382         test_request_firmware_nowait_custom $i xzonly
383 done
384
385 exit 0