129a1c00cSLuis R. Rodriguez#!/bin/bash 2b2441318SGreg Kroah-Hartman# SPDX-License-Identifier: GPL-2.0 3823b0221SLuis R. Rodriguez# This validates that the kernel will fall back to using the fallback mechanism 4823b0221SLuis R. Rodriguez# to load firmware it can't find on disk itself. We must request a firmware 5823b0221SLuis R. Rodriguez# that the kernel won't find, and any installed helper (e.g. udev) also 6823b0221SLuis R. Rodriguez# won't find so that we can do the load ourself manually. 7823b0221SLuis R. Rodriguezset -e 8823b0221SLuis R. Rodriguez 9f5a61451SLuis R. RodriguezTEST_REQS_FW_SYSFS_FALLBACK="yes" 10f5a61451SLuis R. RodriguezTEST_REQS_FW_SET_CUSTOM_PATH="no" 1129a1c00cSLuis R. RodriguezTEST_DIR=$(dirname $0) 1229a1c00cSLuis R. Rodriguezsource $TEST_DIR/fw_lib.sh 13823b0221SLuis R. Rodriguez 1429a1c00cSLuis R. Rodriguezcheck_mods 15f5a61451SLuis R. Rodriguezcheck_setup 16f5a61451SLuis R. Rodriguezverify_reqs 17f5a61451SLuis R. Rodriguezsetup_tmp_file 18823b0221SLuis R. Rodriguez 19f5a61451SLuis R. Rodrigueztrap "test_finish" EXIT 20823b0221SLuis R. Rodriguez 21823b0221SLuis R. Rodriguezload_fw() 22823b0221SLuis R. Rodriguez{ 23823b0221SLuis R. Rodriguez local name="$1" 24823b0221SLuis R. Rodriguez local file="$2" 25823b0221SLuis R. Rodriguez 26823b0221SLuis R. Rodriguez # This will block until our load (below) has finished. 27823b0221SLuis R. Rodriguez echo -n "$name" >"$DIR"/trigger_request & 28823b0221SLuis R. Rodriguez 29823b0221SLuis R. Rodriguez # Give kernel a chance to react. 30823b0221SLuis R. Rodriguez local timeout=10 31823b0221SLuis R. Rodriguez while [ ! -e "$DIR"/"$name"/loading ]; do 32823b0221SLuis R. Rodriguez sleep 0.1 33823b0221SLuis R. Rodriguez timeout=$(( $timeout - 1 )) 34823b0221SLuis R. Rodriguez if [ "$timeout" -eq 0 ]; then 35823b0221SLuis R. Rodriguez echo "$0: firmware interface never appeared" >&2 36823b0221SLuis R. Rodriguez exit 1 37823b0221SLuis R. Rodriguez fi 38823b0221SLuis R. Rodriguez done 39823b0221SLuis R. Rodriguez 40823b0221SLuis R. Rodriguez echo 1 >"$DIR"/"$name"/loading 41823b0221SLuis R. Rodriguez cat "$file" >"$DIR"/"$name"/data 42823b0221SLuis R. Rodriguez echo 0 >"$DIR"/"$name"/loading 43823b0221SLuis R. Rodriguez 44823b0221SLuis R. Rodriguez # Wait for request to finish. 45823b0221SLuis R. Rodriguez wait 46823b0221SLuis R. Rodriguez} 47823b0221SLuis R. Rodriguez 48eb67bc3fSLuis R. Rodriguezload_fw_cancel() 49eb67bc3fSLuis R. Rodriguez{ 50eb67bc3fSLuis R. Rodriguez local name="$1" 51eb67bc3fSLuis R. Rodriguez local file="$2" 52eb67bc3fSLuis R. Rodriguez 53eb67bc3fSLuis R. Rodriguez # This will block until our load (below) has finished. 54eb67bc3fSLuis R. Rodriguez echo -n "$name" >"$DIR"/trigger_request 2>/dev/null & 55eb67bc3fSLuis R. Rodriguez 56eb67bc3fSLuis R. Rodriguez # Give kernel a chance to react. 57eb67bc3fSLuis R. Rodriguez local timeout=10 58eb67bc3fSLuis R. Rodriguez while [ ! -e "$DIR"/"$name"/loading ]; do 59eb67bc3fSLuis R. Rodriguez sleep 0.1 60eb67bc3fSLuis R. Rodriguez timeout=$(( $timeout - 1 )) 61eb67bc3fSLuis R. Rodriguez if [ "$timeout" -eq 0 ]; then 62eb67bc3fSLuis R. Rodriguez echo "$0: firmware interface never appeared" >&2 63eb67bc3fSLuis R. Rodriguez exit 1 64eb67bc3fSLuis R. Rodriguez fi 65eb67bc3fSLuis R. Rodriguez done 66eb67bc3fSLuis R. Rodriguez 67eb67bc3fSLuis R. Rodriguez echo -1 >"$DIR"/"$name"/loading 68eb67bc3fSLuis R. Rodriguez 69eb67bc3fSLuis R. Rodriguez # Wait for request to finish. 70eb67bc3fSLuis R. Rodriguez wait 71eb67bc3fSLuis R. Rodriguez} 72eb67bc3fSLuis R. Rodriguez 73061132d2SLuis R. Rodriguezload_fw_custom() 74061132d2SLuis R. Rodriguez{ 75c3e0d179SAmit Pundir if [ ! -e "$DIR"/trigger_custom_fallback ]; then 76c3e0d179SAmit Pundir echo "$0: custom fallback trigger not present, ignoring test" >&2 77*a6a9be92SShuah Khan (Samsung OSG) exit $ksft_skip 78c3e0d179SAmit Pundir fi 79c3e0d179SAmit Pundir 80061132d2SLuis R. Rodriguez local name="$1" 81061132d2SLuis R. Rodriguez local file="$2" 82061132d2SLuis R. Rodriguez 83061132d2SLuis R. Rodriguez echo -n "$name" >"$DIR"/trigger_custom_fallback 2>/dev/null & 84061132d2SLuis R. Rodriguez 85061132d2SLuis R. Rodriguez # Give kernel a chance to react. 86061132d2SLuis R. Rodriguez local timeout=10 87061132d2SLuis R. Rodriguez while [ ! -e "$DIR"/"$name"/loading ]; do 88061132d2SLuis R. Rodriguez sleep 0.1 89061132d2SLuis R. Rodriguez timeout=$(( $timeout - 1 )) 90061132d2SLuis R. Rodriguez if [ "$timeout" -eq 0 ]; then 91061132d2SLuis R. Rodriguez echo "$0: firmware interface never appeared" >&2 92061132d2SLuis R. Rodriguez exit 1 93061132d2SLuis R. Rodriguez fi 94061132d2SLuis R. Rodriguez done 95061132d2SLuis R. Rodriguez 96061132d2SLuis R. Rodriguez echo 1 >"$DIR"/"$name"/loading 97061132d2SLuis R. Rodriguez cat "$file" >"$DIR"/"$name"/data 98061132d2SLuis R. Rodriguez echo 0 >"$DIR"/"$name"/loading 99061132d2SLuis R. Rodriguez 100061132d2SLuis R. Rodriguez # Wait for request to finish. 101061132d2SLuis R. Rodriguez wait 102c3e0d179SAmit Pundir return 0 103061132d2SLuis R. Rodriguez} 104061132d2SLuis R. Rodriguez 105061132d2SLuis R. Rodriguez 106061132d2SLuis R. Rodriguezload_fw_custom_cancel() 107061132d2SLuis R. Rodriguez{ 108c3e0d179SAmit Pundir if [ ! -e "$DIR"/trigger_custom_fallback ]; then 109c3e0d179SAmit Pundir echo "$0: canceling custom fallback trigger not present, ignoring test" >&2 110*a6a9be92SShuah Khan (Samsung OSG) exit $ksft_skip 111c3e0d179SAmit Pundir fi 112c3e0d179SAmit Pundir 113061132d2SLuis R. Rodriguez local name="$1" 114061132d2SLuis R. Rodriguez local file="$2" 115061132d2SLuis R. Rodriguez 116061132d2SLuis R. Rodriguez echo -n "$name" >"$DIR"/trigger_custom_fallback 2>/dev/null & 117061132d2SLuis R. Rodriguez 118061132d2SLuis R. Rodriguez # Give kernel a chance to react. 119061132d2SLuis R. Rodriguez local timeout=10 120061132d2SLuis R. Rodriguez while [ ! -e "$DIR"/"$name"/loading ]; do 121061132d2SLuis R. Rodriguez sleep 0.1 122061132d2SLuis R. Rodriguez timeout=$(( $timeout - 1 )) 123061132d2SLuis R. Rodriguez if [ "$timeout" -eq 0 ]; then 124061132d2SLuis R. Rodriguez echo "$0: firmware interface never appeared" >&2 125061132d2SLuis R. Rodriguez exit 1 126061132d2SLuis R. Rodriguez fi 127061132d2SLuis R. Rodriguez done 128061132d2SLuis R. Rodriguez 129061132d2SLuis R. Rodriguez echo -1 >"$DIR"/"$name"/loading 130061132d2SLuis R. Rodriguez 131061132d2SLuis R. Rodriguez # Wait for request to finish. 132061132d2SLuis R. Rodriguez wait 133c3e0d179SAmit Pundir return 0 134061132d2SLuis R. Rodriguez} 135061132d2SLuis R. Rodriguez 1360d1f417eSLuis R. Rodriguezload_fw_fallback_with_child() 1370d1f417eSLuis R. Rodriguez{ 1380d1f417eSLuis R. Rodriguez local name="$1" 1390d1f417eSLuis R. Rodriguez local file="$2" 1400d1f417eSLuis R. Rodriguez 1410d1f417eSLuis R. Rodriguez # This is the value already set but we want to be explicit 1420d1f417eSLuis R. Rodriguez echo 4 >/sys/class/firmware/timeout 1430d1f417eSLuis R. Rodriguez 1440d1f417eSLuis R. Rodriguez sleep 1 & 1450d1f417eSLuis R. Rodriguez SECONDS_BEFORE=$(date +%s) 1460d1f417eSLuis R. Rodriguez echo -n "$name" >"$DIR"/trigger_request 2>/dev/null 1470d1f417eSLuis R. Rodriguez SECONDS_AFTER=$(date +%s) 1480d1f417eSLuis R. Rodriguez SECONDS_DELTA=$(($SECONDS_AFTER - $SECONDS_BEFORE)) 1490d1f417eSLuis R. Rodriguez if [ "$SECONDS_DELTA" -lt 4 ]; then 1500d1f417eSLuis R. Rodriguez RET=1 1510d1f417eSLuis R. Rodriguez else 1520d1f417eSLuis R. Rodriguez RET=0 1530d1f417eSLuis R. Rodriguez fi 1540d1f417eSLuis R. Rodriguez wait 1550d1f417eSLuis R. Rodriguez return $RET 1560d1f417eSLuis R. Rodriguez} 157061132d2SLuis R. Rodriguez 158881c23deSLuis R. Rodrigueztest_syfs_timeout() 159881c23deSLuis R. Rodriguez{ 160823b0221SLuis R. Rodriguez DEVPATH="$DIR"/"nope-$NAME"/loading 161823b0221SLuis R. Rodriguez 162823b0221SLuis R. Rodriguez # Test failure when doing nothing (timeout works). 163823b0221SLuis R. Rodriguez echo -n 2 >/sys/class/firmware/timeout 164823b0221SLuis R. Rodriguez echo -n "nope-$NAME" >"$DIR"/trigger_request 2>/dev/null & 165823b0221SLuis R. Rodriguez 166823b0221SLuis R. Rodriguez # Give the kernel some time to load the loading file, must be less 167823b0221SLuis R. Rodriguez # than the timeout above. 168823b0221SLuis R. Rodriguez sleep 1 169823b0221SLuis R. Rodriguez if [ ! -f $DEVPATH ]; then 170823b0221SLuis R. Rodriguez echo "$0: fallback mechanism immediately cancelled" 171823b0221SLuis R. Rodriguez echo "" 172823b0221SLuis R. Rodriguez echo "The file never appeared: $DEVPATH" 173823b0221SLuis R. Rodriguez echo "" 174823b0221SLuis R. Rodriguez echo "This might be a distribution udev rule setup by your distribution" 175823b0221SLuis R. Rodriguez echo "to immediately cancel all fallback requests, this must be" 176823b0221SLuis R. Rodriguez echo "removed before running these tests. To confirm look for" 177823b0221SLuis R. Rodriguez echo "a firmware rule like /lib/udev/rules.d/50-firmware.rules" 178823b0221SLuis R. Rodriguez echo "and see if you have something like this:" 179823b0221SLuis R. Rodriguez echo "" 180823b0221SLuis R. Rodriguez echo "SUBSYSTEM==\"firmware\", ACTION==\"add\", ATTR{loading}=\"-1\"" 181823b0221SLuis R. Rodriguez echo "" 182823b0221SLuis R. Rodriguez echo "If you do remove this file or comment out this line before" 183823b0221SLuis R. Rodriguez echo "proceeding with these tests." 184823b0221SLuis R. Rodriguez exit 1 185823b0221SLuis R. Rodriguez fi 186823b0221SLuis R. Rodriguez 187823b0221SLuis R. Rodriguez if diff -q "$FW" /dev/test_firmware >/dev/null ; then 188823b0221SLuis R. Rodriguez echo "$0: firmware was not expected to match" >&2 189823b0221SLuis R. Rodriguez exit 1 190823b0221SLuis R. Rodriguez else 191823b0221SLuis R. Rodriguez echo "$0: timeout works" 192823b0221SLuis R. Rodriguez fi 193881c23deSLuis R. Rodriguez} 194881c23deSLuis R. Rodriguez 19559106c81SLuis R. Rodriguezrun_sysfs_main_tests() 19659106c81SLuis R. Rodriguez{ 197881c23deSLuis R. Rodriguez test_syfs_timeout 198823b0221SLuis R. Rodriguez # Put timeout high enough for us to do work but not so long that failures 199823b0221SLuis R. Rodriguez # slow down this test too much. 200823b0221SLuis R. Rodriguez echo 4 >/sys/class/firmware/timeout 201823b0221SLuis R. Rodriguez 202823b0221SLuis R. Rodriguez # Load this script instead of the desired firmware. 203823b0221SLuis R. Rodriguez load_fw "$NAME" "$0" 204823b0221SLuis R. Rodriguez if diff -q "$FW" /dev/test_firmware >/dev/null ; then 205823b0221SLuis R. Rodriguez echo "$0: firmware was not expected to match" >&2 206823b0221SLuis R. Rodriguez exit 1 207823b0221SLuis R. Rodriguez else 208823b0221SLuis R. Rodriguez echo "$0: firmware comparison works" 209823b0221SLuis R. Rodriguez fi 210823b0221SLuis R. Rodriguez 211823b0221SLuis R. Rodriguez # Do a proper load, which should work correctly. 212823b0221SLuis R. Rodriguez load_fw "$NAME" "$FW" 213823b0221SLuis R. Rodriguez if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then 214823b0221SLuis R. Rodriguez echo "$0: firmware was not loaded" >&2 215823b0221SLuis R. Rodriguez exit 1 216823b0221SLuis R. Rodriguez else 217823b0221SLuis R. Rodriguez echo "$0: fallback mechanism works" 218eb67bc3fSLuis R. Rodriguez fi 219823b0221SLuis R. Rodriguez 220eb67bc3fSLuis R. Rodriguez load_fw_cancel "nope-$NAME" "$FW" 221eb67bc3fSLuis R. Rodriguez if diff -q "$FW" /dev/test_firmware >/dev/null ; then 222eb67bc3fSLuis R. Rodriguez echo "$0: firmware was expected to be cancelled" >&2 223eb67bc3fSLuis R. Rodriguez exit 1 224eb67bc3fSLuis R. Rodriguez else 225eb67bc3fSLuis R. Rodriguez echo "$0: cancelling fallback mechanism works" 226823b0221SLuis R. Rodriguez fi 227823b0221SLuis R. Rodriguez 22859106c81SLuis R. Rodriguez set +e 22959106c81SLuis R. Rodriguez load_fw_fallback_with_child "nope-signal-$NAME" "$FW" 23059106c81SLuis R. Rodriguez if [ "$?" -eq 0 ]; then 23159106c81SLuis R. Rodriguez echo "$0: SIGCHLD on sync ignored as expected" >&2 23259106c81SLuis R. Rodriguez else 23359106c81SLuis R. Rodriguez echo "$0: error - sync firmware request cancelled due to SIGCHLD" >&2 23459106c81SLuis R. Rodriguez exit 1 23559106c81SLuis R. Rodriguez fi 23659106c81SLuis R. Rodriguez set -e 23759106c81SLuis R. Rodriguez} 23859106c81SLuis R. Rodriguez 23982bdf495SLuis R. Rodriguezrun_sysfs_custom_load_tests() 24082bdf495SLuis R. Rodriguez{ 2419952db75SLuis R. Rodriguez RANDOM_FILE_PATH=$(setup_random_file) 2429952db75SLuis R. Rodriguez RANDOM_FILE="$(basename $RANDOM_FILE_PATH)" 2439952db75SLuis R. Rodriguez if load_fw_custom "$RANDOM_FILE" "$RANDOM_FILE_PATH" ; then 2449952db75SLuis R. Rodriguez if ! diff -q "$RANDOM_FILE_PATH" /dev/test_firmware >/dev/null ; then 24582bdf495SLuis R. Rodriguez echo "$0: firmware was not loaded" >&2 24682bdf495SLuis R. Rodriguez exit 1 24782bdf495SLuis R. Rodriguez else 24882bdf495SLuis R. Rodriguez echo "$0: custom fallback loading mechanism works" 24982bdf495SLuis R. Rodriguez fi 25082bdf495SLuis R. Rodriguez fi 25159106c81SLuis R. Rodriguez 2529952db75SLuis R. Rodriguez RANDOM_FILE_PATH=$(setup_random_file) 2539952db75SLuis R. Rodriguez RANDOM_FILE="$(basename $RANDOM_FILE_PATH)" 2549952db75SLuis R. Rodriguez if load_fw_custom "$RANDOM_FILE" "$RANDOM_FILE_PATH" ; then 2559952db75SLuis R. Rodriguez if ! diff -q "$RANDOM_FILE_PATH" /dev/test_firmware >/dev/null ; then 256061132d2SLuis R. Rodriguez echo "$0: firmware was not loaded" >&2 257061132d2SLuis R. Rodriguez exit 1 258061132d2SLuis R. Rodriguez else 259061132d2SLuis R. Rodriguez echo "$0: custom fallback loading mechanism works" 260061132d2SLuis R. Rodriguez fi 261c3e0d179SAmit Pundir fi 262061132d2SLuis R. Rodriguez 2639952db75SLuis R. Rodriguez RANDOM_FILE_REAL="$RANDOM_FILE_PATH" 2649952db75SLuis R. Rodriguez FAKE_RANDOM_FILE_PATH=$(setup_random_file_fake) 2659952db75SLuis R. Rodriguez FAKE_RANDOM_FILE="$(basename $FAKE_RANDOM_FILE_PATH)" 2669952db75SLuis R. Rodriguez 2679952db75SLuis R. Rodriguez if load_fw_custom_cancel "$FAKE_RANDOM_FILE" "$RANDOM_FILE_REAL" ; then 2689952db75SLuis R. Rodriguez if diff -q "$RANDOM_FILE_PATH" /dev/test_firmware >/dev/null ; then 269061132d2SLuis R. Rodriguez echo "$0: firmware was expected to be cancelled" >&2 270061132d2SLuis R. Rodriguez exit 1 271061132d2SLuis R. Rodriguez else 272061132d2SLuis R. Rodriguez echo "$0: cancelling custom fallback mechanism works" 273061132d2SLuis R. Rodriguez fi 274c3e0d179SAmit Pundir fi 27582bdf495SLuis R. Rodriguez} 27682bdf495SLuis R. Rodriguez 277ef557787SLuis R. Rodriguezif [ "$HAS_FW_LOADER_USER_HELPER_FALLBACK" = "yes" ]; then 27882bdf495SLuis R. Rodriguez run_sysfs_main_tests 279ef557787SLuis R. Rodriguezfi 280ef557787SLuis R. Rodriguez 28182bdf495SLuis R. Rodriguezrun_sysfs_custom_load_tests 282061132d2SLuis R. Rodriguez 283823b0221SLuis R. Rodriguezexit 0 284