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_sync_direct() 120{ 121 echo 1 > $DIR/config_sync_direct 122} 123 124config_unset_sync_direct() 125{ 126 echo 0 > $DIR/config_sync_direct 127} 128 129config_set_uevent() 130{ 131 echo 1 > $DIR/config_send_uevent 132} 133 134config_unset_uevent() 135{ 136 echo 0 > $DIR/config_send_uevent 137} 138 139config_trigger_sync() 140{ 141 echo -n 1 > $DIR/trigger_batched_requests 2>/dev/null 142} 143 144config_trigger_async() 145{ 146 echo -n 1 > $DIR/trigger_batched_requests_async 2> /dev/null 147} 148 149config_set_read_fw_idx() 150{ 151 echo -n $1 > $DIR/config_read_fw_idx 2> /dev/null 152} 153 154read_firmwares() 155{ 156 for i in $(seq 0 3); do 157 config_set_read_fw_idx $i 158 # Verify the contents match 159 if ! diff -q "$FW" $DIR/read_firmware 2>/dev/null ; then 160 echo "request #$i: firmware was not loaded" >&2 161 exit 1 162 fi 163 done 164} 165 166read_firmwares_expect_nofile() 167{ 168 for i in $(seq 0 3); do 169 config_set_read_fw_idx $i 170 # Ensures contents differ 171 if diff -q "$FW" $DIR/read_firmware 2>/dev/null ; then 172 echo "request $i: file was not expected to match" >&2 173 exit 1 174 fi 175 done 176} 177 178test_batched_request_firmware_nofile() 179{ 180 echo -n "Batched request_firmware() nofile try #$1: " 181 config_reset 182 config_set_name nope-test-firmware.bin 183 config_trigger_sync 184 read_firmwares_expect_nofile 185 release_all_firmware 186 echo "OK" 187} 188 189test_batched_request_firmware_direct_nofile() 190{ 191 echo -n "Batched request_firmware_direct() nofile try #$1: " 192 config_reset 193 config_set_name nope-test-firmware.bin 194 config_set_sync_direct 195 config_trigger_sync 196 release_all_firmware 197 echo "OK" 198} 199 200test_request_firmware_nowait_uevent_nofile() 201{ 202 echo -n "Batched request_firmware_nowait(uevent=true) nofile try #$1: " 203 config_reset 204 config_set_name nope-test-firmware.bin 205 config_trigger_async 206 release_all_firmware 207 echo "OK" 208} 209 210test_wait_and_cancel_custom_load() 211{ 212 if [ "$HAS_FW_LOADER_USER_HELPER" != "yes" ]; then 213 return 214 fi 215 local timeout=10 216 name=$1 217 while [ ! -e "$DIR"/"$name"/loading ]; do 218 sleep 0.1 219 timeout=$(( $timeout - 1 )) 220 if [ "$timeout" -eq 0 ]; then 221 echo "firmware interface never appeared:" >&2 222 echo "$DIR/$name/loading" >&2 223 exit 1 224 fi 225 done 226 echo -1 >"$DIR"/"$name"/loading 227} 228 229test_request_firmware_nowait_custom_nofile() 230{ 231 echo -n "Batched request_firmware_nowait(uevent=false) nofile try #$1: " 232 config_reset 233 config_unset_uevent 234 RANDOM_FILE_PATH=$(setup_random_file_fake) 235 RANDOM_FILE="$(basename $RANDOM_FILE_PATH)" 236 config_set_name $RANDOM_FILE 237 config_trigger_async & 238 test_wait_and_cancel_custom_load $RANDOM_FILE 239 wait 240 release_all_firmware 241 echo "OK" 242} 243 244test_batched_request_firmware() 245{ 246 echo -n "Batched request_firmware() try #$1: " 247 config_reset 248 config_trigger_sync 249 read_firmwares 250 release_all_firmware 251 echo "OK" 252} 253 254test_batched_request_firmware_direct() 255{ 256 echo -n "Batched request_firmware_direct() try #$1: " 257 config_reset 258 config_set_sync_direct 259 config_trigger_sync 260 release_all_firmware 261 echo "OK" 262} 263 264test_request_firmware_nowait_uevent() 265{ 266 echo -n "Batched request_firmware_nowait(uevent=true) try #$1: " 267 config_reset 268 config_trigger_async 269 release_all_firmware 270 echo "OK" 271} 272 273test_request_firmware_nowait_custom() 274{ 275 echo -n "Batched request_firmware_nowait(uevent=false) try #$1: " 276 config_reset 277 config_unset_uevent 278 RANDOM_FILE_PATH=$(setup_random_file) 279 RANDOM_FILE="$(basename $RANDOM_FILE_PATH)" 280 config_set_name $RANDOM_FILE 281 config_trigger_async 282 release_all_firmware 283 echo "OK" 284} 285 286# Only continue if batched request triggers are present on the 287# test-firmware driver 288test_config_present 289 290# test with the file present 291echo 292echo "Testing with the file present..." 293for i in $(seq 1 5); do 294 test_batched_request_firmware $i 295done 296 297for i in $(seq 1 5); do 298 test_batched_request_firmware_direct $i 299done 300 301for i in $(seq 1 5); do 302 test_request_firmware_nowait_uevent $i 303done 304 305for i in $(seq 1 5); do 306 test_request_firmware_nowait_custom $i 307done 308 309# Test for file not found, errors are expected, the failure would be 310# a hung task, which would require a hard reset. 311echo 312echo "Testing with the file missing..." 313for i in $(seq 1 5); do 314 test_batched_request_firmware_nofile $i 315done 316 317for i in $(seq 1 5); do 318 test_batched_request_firmware_direct_nofile $i 319done 320 321for i in $(seq 1 5); do 322 test_request_firmware_nowait_uevent_nofile $i 323done 324 325for i in $(seq 1 5); do 326 test_request_firmware_nowait_custom_nofile $i 327done 328 329exit 0 330