1 #!/bin/bash 1 #!/bin/bash 2 # SPDX-License-Identifier: GPL-2.0 2 # SPDX-License-Identifier: GPL-2.0 3 # This validates that the kernel will fall bac 3 # This validates that the kernel will fall back to using the fallback mechanism 4 # to load firmware it can't find on disk itsel 4 # to load firmware it can't find on disk itself. We must request a firmware 5 # that the kernel won't find, and any installe 5 # that the kernel won't find, and any installed helper (e.g. udev) also 6 # won't find so that we can do the load oursel 6 # won't find so that we can do the load ourself manually. 7 set -e 7 set -e 8 8 9 TEST_REQS_FW_SYSFS_FALLBACK="yes" 9 TEST_REQS_FW_SYSFS_FALLBACK="yes" 10 TEST_REQS_FW_SET_CUSTOM_PATH="no" 10 TEST_REQS_FW_SET_CUSTOM_PATH="no" 11 TEST_DIR=$(dirname $0) 11 TEST_DIR=$(dirname $0) 12 source $TEST_DIR/fw_lib.sh 12 source $TEST_DIR/fw_lib.sh 13 13 14 check_mods 14 check_mods 15 check_setup 15 check_setup 16 verify_reqs 16 verify_reqs 17 setup_tmp_file 17 setup_tmp_file 18 18 19 trap "test_finish" EXIT 19 trap "test_finish" EXIT 20 20 21 load_fw() 21 load_fw() 22 { 22 { 23 local name="$1" 23 local name="$1" 24 local file="$2" 24 local file="$2" 25 25 26 # This will block until our load (belo 26 # This will block until our load (below) has finished. 27 echo -n "$name" >"$DIR"/trigger_reques 27 echo -n "$name" >"$DIR"/trigger_request & 28 28 29 # Give kernel a chance to react. 29 # Give kernel a chance to react. 30 local timeout=10 30 local timeout=10 31 while [ ! -e "$DIR"/"$name"/loading ]; 31 while [ ! -e "$DIR"/"$name"/loading ]; do 32 sleep 0.1 32 sleep 0.1 33 timeout=$(( $timeout - 1 )) 33 timeout=$(( $timeout - 1 )) 34 if [ "$timeout" -eq 0 ]; then 34 if [ "$timeout" -eq 0 ]; then 35 echo "$0: firmware int 35 echo "$0: firmware interface never appeared" >&2 36 exit 1 36 exit 1 37 fi 37 fi 38 done 38 done 39 39 40 echo 1 >"$DIR"/"$name"/loading 40 echo 1 >"$DIR"/"$name"/loading 41 cat "$file" >"$DIR"/"$name"/data 41 cat "$file" >"$DIR"/"$name"/data 42 echo 0 >"$DIR"/"$name"/loading 42 echo 0 >"$DIR"/"$name"/loading 43 43 44 # Wait for request to finish. 44 # Wait for request to finish. 45 wait 45 wait 46 } 46 } 47 47 48 load_fw_cancel() 48 load_fw_cancel() 49 { 49 { 50 local name="$1" 50 local name="$1" 51 local file="$2" 51 local file="$2" 52 52 53 # This will block until our load (belo 53 # This will block until our load (below) has finished. 54 echo -n "$name" >"$DIR"/trigger_reques 54 echo -n "$name" >"$DIR"/trigger_request 2>/dev/null & 55 55 56 # Give kernel a chance to react. 56 # Give kernel a chance to react. 57 local timeout=10 57 local timeout=10 58 while [ ! -e "$DIR"/"$name"/loading ]; 58 while [ ! -e "$DIR"/"$name"/loading ]; do 59 sleep 0.1 59 sleep 0.1 60 timeout=$(( $timeout - 1 )) 60 timeout=$(( $timeout - 1 )) 61 if [ "$timeout" -eq 0 ]; then 61 if [ "$timeout" -eq 0 ]; then 62 echo "$0: firmware int 62 echo "$0: firmware interface never appeared" >&2 63 exit 1 63 exit 1 64 fi 64 fi 65 done 65 done 66 66 67 echo -1 >"$DIR"/"$name"/loading 67 echo -1 >"$DIR"/"$name"/loading 68 68 69 # Wait for request to finish. 69 # Wait for request to finish. 70 wait 70 wait 71 } 71 } 72 72 73 load_fw_custom() 73 load_fw_custom() 74 { 74 { 75 if [ ! -e "$DIR"/trigger_custom_fallba 75 if [ ! -e "$DIR"/trigger_custom_fallback ]; then 76 echo "$0: custom fallback trig 76 echo "$0: custom fallback trigger not present, ignoring test" >&2 77 exit $ksft_skip 77 exit $ksft_skip 78 fi 78 fi 79 79 80 local name="$1" 80 local name="$1" 81 local file="$2" 81 local file="$2" 82 82 83 echo -n "$name" >"$DIR"/trigger_custom 83 echo -n "$name" >"$DIR"/trigger_custom_fallback 2>/dev/null & 84 84 85 # Give kernel a chance to react. 85 # Give kernel a chance to react. 86 local timeout=10 86 local timeout=10 87 while [ ! -e "$DIR"/"$name"/loading ]; 87 while [ ! -e "$DIR"/"$name"/loading ]; do 88 sleep 0.1 88 sleep 0.1 89 timeout=$(( $timeout - 1 )) 89 timeout=$(( $timeout - 1 )) 90 if [ "$timeout" -eq 0 ]; then 90 if [ "$timeout" -eq 0 ]; then 91 echo "$0: firmware int 91 echo "$0: firmware interface never appeared" >&2 92 exit 1 92 exit 1 93 fi 93 fi 94 done 94 done 95 95 96 echo 1 >"$DIR"/"$name"/loading 96 echo 1 >"$DIR"/"$name"/loading 97 cat "$file" >"$DIR"/"$name"/data 97 cat "$file" >"$DIR"/"$name"/data 98 echo 0 >"$DIR"/"$name"/loading 98 echo 0 >"$DIR"/"$name"/loading 99 99 100 # Wait for request to finish. 100 # Wait for request to finish. 101 wait 101 wait 102 return 0 102 return 0 103 } 103 } 104 104 105 105 106 load_fw_custom_cancel() 106 load_fw_custom_cancel() 107 { 107 { 108 if [ ! -e "$DIR"/trigger_custom_fallba 108 if [ ! -e "$DIR"/trigger_custom_fallback ]; then 109 echo "$0: canceling custom fal 109 echo "$0: canceling custom fallback trigger not present, ignoring test" >&2 110 exit $ksft_skip 110 exit $ksft_skip 111 fi 111 fi 112 112 113 local name="$1" 113 local name="$1" 114 local file="$2" 114 local file="$2" 115 115 116 echo -n "$name" >"$DIR"/trigger_custom 116 echo -n "$name" >"$DIR"/trigger_custom_fallback 2>/dev/null & 117 117 118 # Give kernel a chance to react. 118 # Give kernel a chance to react. 119 local timeout=10 119 local timeout=10 120 while [ ! -e "$DIR"/"$name"/loading ]; 120 while [ ! -e "$DIR"/"$name"/loading ]; do 121 sleep 0.1 121 sleep 0.1 122 timeout=$(( $timeout - 1 )) 122 timeout=$(( $timeout - 1 )) 123 if [ "$timeout" -eq 0 ]; then 123 if [ "$timeout" -eq 0 ]; then 124 echo "$0: firmware int 124 echo "$0: firmware interface never appeared" >&2 125 exit 1 125 exit 1 126 fi 126 fi 127 done 127 done 128 128 129 echo -1 >"$DIR"/"$name"/loading 129 echo -1 >"$DIR"/"$name"/loading 130 130 131 # Wait for request to finish. 131 # Wait for request to finish. 132 wait 132 wait 133 return 0 133 return 0 134 } 134 } 135 135 136 load_fw_fallback_with_child() 136 load_fw_fallback_with_child() 137 { 137 { 138 local name="$1" 138 local name="$1" 139 local file="$2" 139 local file="$2" 140 140 141 # This is the value already set but we 141 # This is the value already set but we want to be explicit 142 echo 4 >/sys/class/firmware/timeout 142 echo 4 >/sys/class/firmware/timeout 143 143 144 sleep 1 & 144 sleep 1 & 145 SECONDS_BEFORE=$(date +%s) 145 SECONDS_BEFORE=$(date +%s) 146 echo -n "$name" >"$DIR"/trigger_reques 146 echo -n "$name" >"$DIR"/trigger_request 2>/dev/null 147 SECONDS_AFTER=$(date +%s) 147 SECONDS_AFTER=$(date +%s) 148 SECONDS_DELTA=$(($SECONDS_AFTER - $SEC 148 SECONDS_DELTA=$(($SECONDS_AFTER - $SECONDS_BEFORE)) 149 if [ "$SECONDS_DELTA" -lt 4 ]; then 149 if [ "$SECONDS_DELTA" -lt 4 ]; then 150 RET=1 150 RET=1 151 else 151 else 152 RET=0 152 RET=0 153 fi 153 fi 154 wait 154 wait 155 return $RET 155 return $RET 156 } 156 } 157 157 158 test_syfs_timeout() 158 test_syfs_timeout() 159 { 159 { 160 DEVPATH="$DIR"/"nope-$NAME"/loading 160 DEVPATH="$DIR"/"nope-$NAME"/loading 161 161 162 # Test failure when doing nothing (tim 162 # Test failure when doing nothing (timeout works). 163 echo -n 2 >/sys/class/firmware/timeout 163 echo -n 2 >/sys/class/firmware/timeout 164 echo -n "nope-$NAME" >"$DIR"/trigger_r 164 echo -n "nope-$NAME" >"$DIR"/trigger_request 2>/dev/null & 165 165 166 # Give the kernel some time to load th 166 # Give the kernel some time to load the loading file, must be less 167 # than the timeout above. 167 # than the timeout above. 168 sleep 1 168 sleep 1 169 if [ ! -f $DEVPATH ]; then 169 if [ ! -f $DEVPATH ]; then 170 echo "$0: fallback mechanism i 170 echo "$0: fallback mechanism immediately cancelled" 171 echo "" 171 echo "" 172 echo "The file never appeared: 172 echo "The file never appeared: $DEVPATH" 173 echo "" 173 echo "" 174 echo "This might be a distribu 174 echo "This might be a distribution udev rule setup by your distribution" 175 echo "to immediately cancel al 175 echo "to immediately cancel all fallback requests, this must be" 176 echo "removed before running t 176 echo "removed before running these tests. To confirm look for" 177 echo "a firmware rule like /li 177 echo "a firmware rule like /lib/udev/rules.d/50-firmware.rules" 178 echo "and see if you have some 178 echo "and see if you have something like this:" 179 echo "" 179 echo "" 180 echo "SUBSYSTEM==\"firmware\", 180 echo "SUBSYSTEM==\"firmware\", ACTION==\"add\", ATTR{loading}=\"-1\"" 181 echo "" 181 echo "" 182 echo "If you do remove this fi 182 echo "If you do remove this file or comment out this line before" 183 echo "proceeding with these te 183 echo "proceeding with these tests." 184 exit 1 184 exit 1 185 fi 185 fi 186 186 187 if diff -q "$FW" /dev/test_firmware >/ 187 if diff -q "$FW" /dev/test_firmware >/dev/null ; then 188 echo "$0: firmware was not exp 188 echo "$0: firmware was not expected to match" >&2 189 exit 1 189 exit 1 190 else 190 else 191 echo "$0: timeout works" 191 echo "$0: timeout works" 192 fi 192 fi 193 } 193 } 194 194 195 run_sysfs_main_tests() 195 run_sysfs_main_tests() 196 { 196 { 197 test_syfs_timeout 197 test_syfs_timeout 198 # Put timeout high enough for us to do 198 # Put timeout high enough for us to do work but not so long that failures 199 # slow down this test too much. 199 # slow down this test too much. 200 echo 4 >/sys/class/firmware/timeout 200 echo 4 >/sys/class/firmware/timeout 201 201 202 # Load this script instead of the desi 202 # Load this script instead of the desired firmware. 203 load_fw "$NAME" "$0" 203 load_fw "$NAME" "$0" 204 if diff -q "$FW" /dev/test_firmware >/ 204 if diff -q "$FW" /dev/test_firmware >/dev/null ; then 205 echo "$0: firmware was not exp 205 echo "$0: firmware was not expected to match" >&2 206 exit 1 206 exit 1 207 else 207 else 208 echo "$0: firmware comparison 208 echo "$0: firmware comparison works" 209 fi 209 fi 210 210 211 # Do a proper load, which should work 211 # Do a proper load, which should work correctly. 212 load_fw "$NAME" "$FW" 212 load_fw "$NAME" "$FW" 213 if ! diff -q "$FW" /dev/test_firmware 213 if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then 214 echo "$0: firmware was not loa 214 echo "$0: firmware was not loaded" >&2 215 exit 1 215 exit 1 216 else 216 else 217 echo "$0: fallback mechanism w 217 echo "$0: fallback mechanism works" 218 fi 218 fi 219 219 220 load_fw_cancel "nope-$NAME" "$FW" 220 load_fw_cancel "nope-$NAME" "$FW" 221 if diff -q "$FW" /dev/test_firmware >/ 221 if diff -q "$FW" /dev/test_firmware >/dev/null ; then 222 echo "$0: firmware was expecte 222 echo "$0: firmware was expected to be cancelled" >&2 223 exit 1 223 exit 1 224 else 224 else 225 echo "$0: cancelling fallback 225 echo "$0: cancelling fallback mechanism works" 226 fi 226 fi 227 227 228 set +e 228 set +e 229 load_fw_fallback_with_child "nope-sign 229 load_fw_fallback_with_child "nope-signal-$NAME" "$FW" 230 if [ "$?" -eq 0 ]; then 230 if [ "$?" -eq 0 ]; then 231 echo "$0: SIGCHLD on sync igno 231 echo "$0: SIGCHLD on sync ignored as expected" >&2 232 else 232 else 233 echo "$0: error - sync firmwar 233 echo "$0: error - sync firmware request cancelled due to SIGCHLD" >&2 234 exit 1 234 exit 1 235 fi 235 fi 236 set -e 236 set -e 237 } 237 } 238 238 239 run_sysfs_custom_load_tests() 239 run_sysfs_custom_load_tests() 240 { 240 { 241 RANDOM_FILE_PATH=$(setup_random_file) 241 RANDOM_FILE_PATH=$(setup_random_file) 242 RANDOM_FILE="$(basename $RANDOM_FILE_P 242 RANDOM_FILE="$(basename $RANDOM_FILE_PATH)" 243 if load_fw_custom "$RANDOM_FILE" "$RAN 243 if load_fw_custom "$RANDOM_FILE" "$RANDOM_FILE_PATH" ; then 244 if ! diff -q "$RANDOM_FILE_PAT 244 if ! diff -q "$RANDOM_FILE_PATH" /dev/test_firmware >/dev/null ; then 245 echo "$0: firmware was 245 echo "$0: firmware was not loaded" >&2 246 exit 1 246 exit 1 247 else 247 else 248 echo "$0: custom fallb 248 echo "$0: custom fallback loading mechanism works" 249 fi 249 fi 250 fi 250 fi 251 251 252 RANDOM_FILE_PATH=$(setup_random_file) 252 RANDOM_FILE_PATH=$(setup_random_file) 253 RANDOM_FILE="$(basename $RANDOM_FILE_P 253 RANDOM_FILE="$(basename $RANDOM_FILE_PATH)" 254 if load_fw_custom "$RANDOM_FILE" "$RAN 254 if load_fw_custom "$RANDOM_FILE" "$RANDOM_FILE_PATH" ; then 255 if ! diff -q "$RANDOM_FILE_PAT 255 if ! diff -q "$RANDOM_FILE_PATH" /dev/test_firmware >/dev/null ; then 256 echo "$0: firmware was 256 echo "$0: firmware was not loaded" >&2 257 exit 1 257 exit 1 258 else 258 else 259 echo "$0: custom fallb 259 echo "$0: custom fallback loading mechanism works" 260 fi 260 fi 261 fi 261 fi 262 262 263 RANDOM_FILE_REAL="$RANDOM_FILE_PATH" 263 RANDOM_FILE_REAL="$RANDOM_FILE_PATH" 264 FAKE_RANDOM_FILE_PATH=$(setup_random_f 264 FAKE_RANDOM_FILE_PATH=$(setup_random_file_fake) 265 FAKE_RANDOM_FILE="$(basename $FAKE_RAN 265 FAKE_RANDOM_FILE="$(basename $FAKE_RANDOM_FILE_PATH)" 266 266 267 if load_fw_custom_cancel "$FAKE_RANDOM 267 if load_fw_custom_cancel "$FAKE_RANDOM_FILE" "$RANDOM_FILE_REAL" ; then 268 if diff -q "$RANDOM_FILE_PATH" 268 if diff -q "$RANDOM_FILE_PATH" /dev/test_firmware >/dev/null ; then 269 echo "$0: firmware was 269 echo "$0: firmware was expected to be cancelled" >&2 270 exit 1 270 exit 1 271 else 271 else 272 echo "$0: cancelling c 272 echo "$0: cancelling custom fallback mechanism works" 273 fi 273 fi 274 fi 274 fi 275 } 275 } 276 276 277 if [ "$HAS_FW_LOADER_USER_HELPER_FALLBACK" = " 277 if [ "$HAS_FW_LOADER_USER_HELPER_FALLBACK" = "yes" ]; then 278 run_sysfs_main_tests 278 run_sysfs_main_tests 279 fi 279 fi 280 280 281 run_sysfs_custom_load_tests 281 run_sysfs_custom_load_tests 282 282 283 exit 0 283 exit 0
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.