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 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 169read_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 181test_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 192test_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 203test_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 213test_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 232test_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 247test_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 257test_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 267test_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 276test_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 291test_config_present 292 293# test with the file present 294echo 295echo "Testing with the file present..." 296for i in $(seq 1 5); do 297 test_batched_request_firmware $i 298done 299 300for i in $(seq 1 5); do 301 test_batched_request_firmware_direct $i 302done 303 304for i in $(seq 1 5); do 305 test_request_firmware_nowait_uevent $i 306done 307 308for i in $(seq 1 5); do 309 test_request_firmware_nowait_custom $i 310done 311 312# Test for file not found, errors are expected, the failure would be 313# a hung task, which would require a hard reset. 314echo 315echo "Testing with the file missing..." 316for i in $(seq 1 5); do 317 test_batched_request_firmware_nofile $i 318done 319 320for i in $(seq 1 5); do 321 test_batched_request_firmware_direct_nofile $i 322done 323 324for i in $(seq 1 5); do 325 test_request_firmware_nowait_uevent_nofile $i 326done 327 328for i in $(seq 1 5); do 329 test_request_firmware_nowait_custom_nofile $i 330done 331 332exit 0 333