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