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. 7set -e 8 9TEST_REQS_FW_SYSFS_FALLBACK="no" 10TEST_REQS_FW_SET_CUSTOM_PATH="yes" 11TEST_DIR=$(dirname $0) 12source $TEST_DIR/fw_lib.sh 13 14check_mods 15check_setup 16verify_reqs 17setup_tmp_file 18 19trap "test_finish" EXIT 20 21if [ "$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 24fi 25 26if printf '\000' >"$DIR"/trigger_request 2> /dev/null; then 27 echo "$0: empty filename should not succeed" >&2 28 exit 1 29fi 30 31if [ ! -e "$DIR"/trigger_async_request ]; then 32 echo "$0: empty filename: async trigger not present, ignoring test" >&2 33 exit $ksft_skip 34else 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 39fi 40 41# Request a firmware that doesn't exist, it should fail. 42if echo -n "nope-$NAME" >"$DIR"/trigger_request 2> /dev/null; then 43 echo "$0: firmware shouldn't have loaded" >&2 44 exit 1 45fi 46if diff -q "$FW" /dev/test_firmware >/dev/null ; then 47 echo "$0: firmware was not expected to match" >&2 48 exit 1 49else 50 if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then 51 echo "$0: timeout works" 52 fi 53fi 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. 57if ! echo -n "$NAME" >"$DIR"/trigger_request ; then 58 echo "$0: could not trigger request" >&2 59 exit 1 60fi 61 62# Verify the contents are what we expect. 63if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then 64 echo "$0: firmware was not loaded" >&2 65 exit 1 66else 67 echo "$0: filesystem loading works" 68fi 69 70# Try the asynchronous version too 71if [ ! -e "$DIR"/trigger_async_request ]; then 72 echo "$0: firmware loading: async trigger not present, ignoring test" >&2 73 exit $ksft_skip 74else 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 87fi 88 89### Batched requests tests 90test_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 104config_reset() 105{ 106 echo 1 > $DIR/reset 107} 108 109release_all_firmware() 110{ 111 echo 1 > $DIR/release_all_firmware 112} 113 114config_set_name() 115{ 116 echo -n $1 > $DIR/config_name 117} 118 119config_set_into_buf() 120{ 121 echo 1 > $DIR/config_into_buf 122} 123 124config_unset_into_buf() 125{ 126 echo 0 > $DIR/config_into_buf 127} 128 129config_set_sync_direct() 130{ 131 echo 1 > $DIR/config_sync_direct 132} 133 134config_unset_sync_direct() 135{ 136 echo 0 > $DIR/config_sync_direct 137} 138 139config_set_uevent() 140{ 141 echo 1 > $DIR/config_send_uevent 142} 143 144config_unset_uevent() 145{ 146 echo 0 > $DIR/config_send_uevent 147} 148 149config_trigger_sync() 150{ 151 echo -n 1 > $DIR/trigger_batched_requests 2>/dev/null 152} 153 154config_trigger_async() 155{ 156 echo -n 1 > $DIR/trigger_batched_requests_async 2> /dev/null 157} 158 159config_set_read_fw_idx() 160{ 161 echo -n $1 > $DIR/config_read_fw_idx 2> /dev/null 162} 163 164read_firmwares() 165{ 166 if [ "$(cat $DIR/config_into_buf)" == "1" ]; then 167 fwfile="$FW_INTO_BUF" 168 else 169 fwfile="$FW" 170 fi 171 if [ "$1" = "xzonly" ]; then 172 fwfile="${fwfile}-orig" 173 fi 174 for i in $(seq 0 3); do 175 config_set_read_fw_idx $i 176 # Verify the contents are what we expect. 177 # -Z required for now -- check for yourself, md5sum 178 # on $FW and DIR/read_firmware will yield the same. Even 179 # cmp agrees, so something is off. 180 if ! diff -q -Z "$fwfile" $DIR/read_firmware 2>/dev/null ; then 181 echo "request #$i: firmware was not loaded" >&2 182 exit 1 183 fi 184 done 185} 186 187read_firmwares_expect_nofile() 188{ 189 for i in $(seq 0 3); do 190 config_set_read_fw_idx $i 191 # Ensures contents differ 192 if diff -q -Z "$FW" $DIR/read_firmware 2>/dev/null ; then 193 echo "request $i: file was not expected to match" >&2 194 exit 1 195 fi 196 done 197} 198 199test_batched_request_firmware_nofile() 200{ 201 echo -n "Batched request_firmware() nofile try #$1: " 202 config_reset 203 config_set_name nope-test-firmware.bin 204 config_trigger_sync 205 read_firmwares_expect_nofile 206 release_all_firmware 207 echo "OK" 208} 209 210test_batched_request_firmware_into_buf_nofile() 211{ 212 echo -n "Batched request_firmware_into_buf() nofile try #$1: " 213 config_reset 214 config_set_name nope-test-firmware.bin 215 config_set_into_buf 216 config_trigger_sync 217 read_firmwares_expect_nofile 218 release_all_firmware 219 echo "OK" 220} 221 222test_batched_request_firmware_direct_nofile() 223{ 224 echo -n "Batched request_firmware_direct() nofile try #$1: " 225 config_reset 226 config_set_name nope-test-firmware.bin 227 config_set_sync_direct 228 config_trigger_sync 229 release_all_firmware 230 echo "OK" 231} 232 233test_request_firmware_nowait_uevent_nofile() 234{ 235 echo -n "Batched request_firmware_nowait(uevent=true) nofile try #$1: " 236 config_reset 237 config_set_name nope-test-firmware.bin 238 config_trigger_async 239 release_all_firmware 240 echo "OK" 241} 242 243test_wait_and_cancel_custom_load() 244{ 245 if [ "$HAS_FW_LOADER_USER_HELPER" != "yes" ]; then 246 return 247 fi 248 local timeout=10 249 name=$1 250 while [ ! -e "$DIR"/"$name"/loading ]; do 251 sleep 0.1 252 timeout=$(( $timeout - 1 )) 253 if [ "$timeout" -eq 0 ]; then 254 echo "firmware interface never appeared:" >&2 255 echo "$DIR/$name/loading" >&2 256 exit 1 257 fi 258 done 259 echo -1 >"$DIR"/"$name"/loading 260} 261 262test_request_firmware_nowait_custom_nofile() 263{ 264 echo -n "Batched request_firmware_nowait(uevent=false) nofile try #$1: " 265 config_reset 266 config_unset_uevent 267 RANDOM_FILE_PATH=$(setup_random_file_fake) 268 RANDOM_FILE="$(basename $RANDOM_FILE_PATH)" 269 config_set_name $RANDOM_FILE 270 config_trigger_async & 271 test_wait_and_cancel_custom_load $RANDOM_FILE 272 wait 273 release_all_firmware 274 echo "OK" 275} 276 277test_batched_request_firmware() 278{ 279 echo -n "Batched request_firmware() $2 try #$1: " 280 config_reset 281 config_trigger_sync 282 read_firmwares $2 283 release_all_firmware 284 echo "OK" 285} 286 287test_batched_request_firmware_into_buf() 288{ 289 echo -n "Batched request_firmware_into_buf() $2 try #$1: " 290 config_reset 291 config_set_name $TEST_FIRMWARE_INTO_BUF_FILENAME 292 config_set_into_buf 293 config_trigger_sync 294 read_firmwares $2 295 release_all_firmware 296 echo "OK" 297} 298 299test_batched_request_firmware_direct() 300{ 301 echo -n "Batched request_firmware_direct() $2 try #$1: " 302 config_reset 303 config_set_sync_direct 304 config_trigger_sync 305 release_all_firmware 306 echo "OK" 307} 308 309test_request_firmware_nowait_uevent() 310{ 311 echo -n "Batched request_firmware_nowait(uevent=true) $2 try #$1: " 312 config_reset 313 config_trigger_async 314 release_all_firmware 315 echo "OK" 316} 317 318test_request_firmware_nowait_custom() 319{ 320 echo -n "Batched request_firmware_nowait(uevent=false) $2 try #$1: " 321 config_reset 322 config_unset_uevent 323 RANDOM_FILE_PATH=$(setup_random_file) 324 RANDOM_FILE="$(basename $RANDOM_FILE_PATH)" 325 if [ "$2" = "both" ]; then 326 xz -9 -C crc32 -k $RANDOM_FILE_PATH 327 elif [ "$2" = "xzonly" ]; then 328 xz -9 -C crc32 $RANDOM_FILE_PATH 329 fi 330 config_set_name $RANDOM_FILE 331 config_trigger_async 332 release_all_firmware 333 echo "OK" 334} 335 336# Only continue if batched request triggers are present on the 337# test-firmware driver 338test_config_present 339 340# test with the file present 341echo 342echo "Testing with the file present..." 343for i in $(seq 1 5); do 344 test_batched_request_firmware $i normal 345done 346 347for i in $(seq 1 5); do 348 test_batched_request_firmware_into_buf $i normal 349done 350 351for i in $(seq 1 5); do 352 test_batched_request_firmware_direct $i normal 353done 354 355for i in $(seq 1 5); do 356 test_request_firmware_nowait_uevent $i normal 357done 358 359for i in $(seq 1 5); do 360 test_request_firmware_nowait_custom $i normal 361done 362 363# Test for file not found, errors are expected, the failure would be 364# a hung task, which would require a hard reset. 365echo 366echo "Testing with the file missing..." 367for i in $(seq 1 5); do 368 test_batched_request_firmware_nofile $i 369done 370 371for i in $(seq 1 5); do 372 test_batched_request_firmware_into_buf_nofile $i 373done 374 375for i in $(seq 1 5); do 376 test_batched_request_firmware_direct_nofile $i 377done 378 379for i in $(seq 1 5); do 380 test_request_firmware_nowait_uevent_nofile $i 381done 382 383for i in $(seq 1 5); do 384 test_request_firmware_nowait_custom_nofile $i 385done 386 387test "$HAS_FW_LOADER_COMPRESS" != "yes" && exit 0 388 389# test with both files present 390xz -9 -C crc32 -k $FW 391config_set_name $NAME 392echo 393echo "Testing with both plain and xz files present..." 394for i in $(seq 1 5); do 395 test_batched_request_firmware $i both 396done 397 398for i in $(seq 1 5); do 399 test_batched_request_firmware_into_buf $i both 400done 401 402for i in $(seq 1 5); do 403 test_batched_request_firmware_direct $i both 404done 405 406for i in $(seq 1 5); do 407 test_request_firmware_nowait_uevent $i both 408done 409 410for i in $(seq 1 5); do 411 test_request_firmware_nowait_custom $i both 412done 413 414# test with only xz file present 415mv "$FW" "${FW}-orig" 416echo 417echo "Testing with only xz file present..." 418for i in $(seq 1 5); do 419 test_batched_request_firmware $i xzonly 420done 421 422for i in $(seq 1 5); do 423 test_batched_request_firmware_into_buf $i xzonly 424done 425 426for i in $(seq 1 5); do 427 test_batched_request_firmware_direct $i xzonly 428done 429 430for i in $(seq 1 5); do 431 test_request_firmware_nowait_uevent $i xzonly 432done 433 434for i in $(seq 1 5); do 435 test_request_firmware_nowait_custom $i xzonly 436done 437 438exit 0 439