mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
283 lines
6.6 KiB
283 lines
6.6 KiB
#!/bin/bash |
|
# SPDX-License-Identifier: GPL-2.0 |
|
# This validates that the kernel will fall back to using the fallback mechanism |
|
# to load firmware it can't find on disk itself. We must request a firmware |
|
# that the kernel won't find, and any installed helper (e.g. udev) also |
|
# won't find so that we can do the load ourself manually. |
|
set -e |
|
|
|
TEST_REQS_FW_SYSFS_FALLBACK="yes" |
|
TEST_REQS_FW_SET_CUSTOM_PATH="no" |
|
TEST_DIR=$(dirname $0) |
|
source $TEST_DIR/fw_lib.sh |
|
|
|
check_mods |
|
check_setup |
|
verify_reqs |
|
setup_tmp_file |
|
|
|
trap "test_finish" EXIT |
|
|
|
load_fw() |
|
{ |
|
local name="$1" |
|
local file="$2" |
|
|
|
# This will block until our load (below) has finished. |
|
echo -n "$name" >"$DIR"/trigger_request & |
|
|
|
# Give kernel a chance to react. |
|
local timeout=10 |
|
while [ ! -e "$DIR"/"$name"/loading ]; do |
|
sleep 0.1 |
|
timeout=$(( $timeout - 1 )) |
|
if [ "$timeout" -eq 0 ]; then |
|
echo "$0: firmware interface never appeared" >&2 |
|
exit 1 |
|
fi |
|
done |
|
|
|
echo 1 >"$DIR"/"$name"/loading |
|
cat "$file" >"$DIR"/"$name"/data |
|
echo 0 >"$DIR"/"$name"/loading |
|
|
|
# Wait for request to finish. |
|
wait |
|
} |
|
|
|
load_fw_cancel() |
|
{ |
|
local name="$1" |
|
local file="$2" |
|
|
|
# This will block until our load (below) has finished. |
|
echo -n "$name" >"$DIR"/trigger_request 2>/dev/null & |
|
|
|
# Give kernel a chance to react. |
|
local timeout=10 |
|
while [ ! -e "$DIR"/"$name"/loading ]; do |
|
sleep 0.1 |
|
timeout=$(( $timeout - 1 )) |
|
if [ "$timeout" -eq 0 ]; then |
|
echo "$0: firmware interface never appeared" >&2 |
|
exit 1 |
|
fi |
|
done |
|
|
|
echo -1 >"$DIR"/"$name"/loading |
|
|
|
# Wait for request to finish. |
|
wait |
|
} |
|
|
|
load_fw_custom() |
|
{ |
|
if [ ! -e "$DIR"/trigger_custom_fallback ]; then |
|
echo "$0: custom fallback trigger not present, ignoring test" >&2 |
|
exit $ksft_skip |
|
fi |
|
|
|
local name="$1" |
|
local file="$2" |
|
|
|
echo -n "$name" >"$DIR"/trigger_custom_fallback 2>/dev/null & |
|
|
|
# Give kernel a chance to react. |
|
local timeout=10 |
|
while [ ! -e "$DIR"/"$name"/loading ]; do |
|
sleep 0.1 |
|
timeout=$(( $timeout - 1 )) |
|
if [ "$timeout" -eq 0 ]; then |
|
echo "$0: firmware interface never appeared" >&2 |
|
exit 1 |
|
fi |
|
done |
|
|
|
echo 1 >"$DIR"/"$name"/loading |
|
cat "$file" >"$DIR"/"$name"/data |
|
echo 0 >"$DIR"/"$name"/loading |
|
|
|
# Wait for request to finish. |
|
wait |
|
return 0 |
|
} |
|
|
|
|
|
load_fw_custom_cancel() |
|
{ |
|
if [ ! -e "$DIR"/trigger_custom_fallback ]; then |
|
echo "$0: canceling custom fallback trigger not present, ignoring test" >&2 |
|
exit $ksft_skip |
|
fi |
|
|
|
local name="$1" |
|
local file="$2" |
|
|
|
echo -n "$name" >"$DIR"/trigger_custom_fallback 2>/dev/null & |
|
|
|
# Give kernel a chance to react. |
|
local timeout=10 |
|
while [ ! -e "$DIR"/"$name"/loading ]; do |
|
sleep 0.1 |
|
timeout=$(( $timeout - 1 )) |
|
if [ "$timeout" -eq 0 ]; then |
|
echo "$0: firmware interface never appeared" >&2 |
|
exit 1 |
|
fi |
|
done |
|
|
|
echo -1 >"$DIR"/"$name"/loading |
|
|
|
# Wait for request to finish. |
|
wait |
|
return 0 |
|
} |
|
|
|
load_fw_fallback_with_child() |
|
{ |
|
local name="$1" |
|
local file="$2" |
|
|
|
# This is the value already set but we want to be explicit |
|
echo 4 >/sys/class/firmware/timeout |
|
|
|
sleep 1 & |
|
SECONDS_BEFORE=$(date +%s) |
|
echo -n "$name" >"$DIR"/trigger_request 2>/dev/null |
|
SECONDS_AFTER=$(date +%s) |
|
SECONDS_DELTA=$(($SECONDS_AFTER - $SECONDS_BEFORE)) |
|
if [ "$SECONDS_DELTA" -lt 4 ]; then |
|
RET=1 |
|
else |
|
RET=0 |
|
fi |
|
wait |
|
return $RET |
|
} |
|
|
|
test_syfs_timeout() |
|
{ |
|
DEVPATH="$DIR"/"nope-$NAME"/loading |
|
|
|
# Test failure when doing nothing (timeout works). |
|
echo -n 2 >/sys/class/firmware/timeout |
|
echo -n "nope-$NAME" >"$DIR"/trigger_request 2>/dev/null & |
|
|
|
# Give the kernel some time to load the loading file, must be less |
|
# than the timeout above. |
|
sleep 1 |
|
if [ ! -f $DEVPATH ]; then |
|
echo "$0: fallback mechanism immediately cancelled" |
|
echo "" |
|
echo "The file never appeared: $DEVPATH" |
|
echo "" |
|
echo "This might be a distribution udev rule setup by your distribution" |
|
echo "to immediately cancel all fallback requests, this must be" |
|
echo "removed before running these tests. To confirm look for" |
|
echo "a firmware rule like /lib/udev/rules.d/50-firmware.rules" |
|
echo "and see if you have something like this:" |
|
echo "" |
|
echo "SUBSYSTEM==\"firmware\", ACTION==\"add\", ATTR{loading}=\"-1\"" |
|
echo "" |
|
echo "If you do remove this file or comment out this line before" |
|
echo "proceeding with these tests." |
|
exit 1 |
|
fi |
|
|
|
if diff -q "$FW" /dev/test_firmware >/dev/null ; then |
|
echo "$0: firmware was not expected to match" >&2 |
|
exit 1 |
|
else |
|
echo "$0: timeout works" |
|
fi |
|
} |
|
|
|
run_sysfs_main_tests() |
|
{ |
|
test_syfs_timeout |
|
# Put timeout high enough for us to do work but not so long that failures |
|
# slow down this test too much. |
|
echo 4 >/sys/class/firmware/timeout |
|
|
|
# Load this script instead of the desired firmware. |
|
load_fw "$NAME" "$0" |
|
if diff -q "$FW" /dev/test_firmware >/dev/null ; then |
|
echo "$0: firmware was not expected to match" >&2 |
|
exit 1 |
|
else |
|
echo "$0: firmware comparison works" |
|
fi |
|
|
|
# Do a proper load, which should work correctly. |
|
load_fw "$NAME" "$FW" |
|
if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then |
|
echo "$0: firmware was not loaded" >&2 |
|
exit 1 |
|
else |
|
echo "$0: fallback mechanism works" |
|
fi |
|
|
|
load_fw_cancel "nope-$NAME" "$FW" |
|
if diff -q "$FW" /dev/test_firmware >/dev/null ; then |
|
echo "$0: firmware was expected to be cancelled" >&2 |
|
exit 1 |
|
else |
|
echo "$0: cancelling fallback mechanism works" |
|
fi |
|
|
|
set +e |
|
load_fw_fallback_with_child "nope-signal-$NAME" "$FW" |
|
if [ "$?" -eq 0 ]; then |
|
echo "$0: SIGCHLD on sync ignored as expected" >&2 |
|
else |
|
echo "$0: error - sync firmware request cancelled due to SIGCHLD" >&2 |
|
exit 1 |
|
fi |
|
set -e |
|
} |
|
|
|
run_sysfs_custom_load_tests() |
|
{ |
|
RANDOM_FILE_PATH=$(setup_random_file) |
|
RANDOM_FILE="$(basename $RANDOM_FILE_PATH)" |
|
if load_fw_custom "$RANDOM_FILE" "$RANDOM_FILE_PATH" ; then |
|
if ! diff -q "$RANDOM_FILE_PATH" /dev/test_firmware >/dev/null ; then |
|
echo "$0: firmware was not loaded" >&2 |
|
exit 1 |
|
else |
|
echo "$0: custom fallback loading mechanism works" |
|
fi |
|
fi |
|
|
|
RANDOM_FILE_PATH=$(setup_random_file) |
|
RANDOM_FILE="$(basename $RANDOM_FILE_PATH)" |
|
if load_fw_custom "$RANDOM_FILE" "$RANDOM_FILE_PATH" ; then |
|
if ! diff -q "$RANDOM_FILE_PATH" /dev/test_firmware >/dev/null ; then |
|
echo "$0: firmware was not loaded" >&2 |
|
exit 1 |
|
else |
|
echo "$0: custom fallback loading mechanism works" |
|
fi |
|
fi |
|
|
|
RANDOM_FILE_REAL="$RANDOM_FILE_PATH" |
|
FAKE_RANDOM_FILE_PATH=$(setup_random_file_fake) |
|
FAKE_RANDOM_FILE="$(basename $FAKE_RANDOM_FILE_PATH)" |
|
|
|
if load_fw_custom_cancel "$FAKE_RANDOM_FILE" "$RANDOM_FILE_REAL" ; then |
|
if diff -q "$RANDOM_FILE_PATH" /dev/test_firmware >/dev/null ; then |
|
echo "$0: firmware was expected to be cancelled" >&2 |
|
exit 1 |
|
else |
|
echo "$0: cancelling custom fallback mechanism works" |
|
fi |
|
fi |
|
} |
|
|
|
if [ "$HAS_FW_LOADER_USER_HELPER_FALLBACK" = "yes" ]; then |
|
run_sysfs_main_tests |
|
fi |
|
|
|
run_sysfs_custom_load_tests |
|
|
|
exit 0
|
|
|