mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-21 10:05:00 +08:00
a37ddddd86
Add selftests to verify the firmware upload mechanism. These test include simple firmware uploads as well as upload cancellation and error injection. The test creates three firmware devices and verifies that they all work correctly and independently. Tested-by: Matthew Gerlach <matthew.gerlach@linux.intel.com> Reviewed-by: Luis Chamberlain <mcgrof@kernel.org> Reviewed-by: Tianfei zhang <tianfei.zhang@intel.com> Signed-off-by: Russ Weight <russell.h.weight@intel.com> Link: https://lore.kernel.org/r/20220426163532.114961-1-russell.h.weight@intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
237 lines
5.4 KiB
Bash
Executable File
237 lines
5.4 KiB
Bash
Executable File
#!/bin/bash
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
|
|
# Library of helpers for test scripts.
|
|
set -e
|
|
|
|
DIR=/sys/devices/virtual/misc/test_firmware
|
|
|
|
PROC_CONFIG="/proc/config.gz"
|
|
TEST_DIR=$(dirname $0)
|
|
|
|
# We need to load a different file to test request_firmware_into_buf
|
|
# I believe the issue is firmware loaded cached vs. non-cached
|
|
# with same filename is bungled.
|
|
# To reproduce rename this to test-firmware.bin
|
|
TEST_FIRMWARE_INTO_BUF_FILENAME=test-firmware-into-buf.bin
|
|
|
|
# Kselftest framework requirement - SKIP code is 4.
|
|
ksft_skip=4
|
|
|
|
print_reqs_exit()
|
|
{
|
|
echo "You must have the following enabled in your kernel:" >&2
|
|
cat $TEST_DIR/config >&2
|
|
exit $ksft_skip
|
|
}
|
|
|
|
test_modprobe()
|
|
{
|
|
if [ ! -d $DIR ]; then
|
|
print_reqs_exit
|
|
fi
|
|
}
|
|
|
|
check_mods()
|
|
{
|
|
local uid=$(id -u)
|
|
if [ $uid -ne 0 ]; then
|
|
echo "skip all tests: must be run as root" >&2
|
|
exit $ksft_skip
|
|
fi
|
|
|
|
trap "test_modprobe" EXIT
|
|
if [ ! -d $DIR ]; then
|
|
modprobe test_firmware
|
|
fi
|
|
if [ ! -f $PROC_CONFIG ]; then
|
|
if modprobe configs 2>/dev/null; then
|
|
echo "Loaded configs module"
|
|
if [ ! -f $PROC_CONFIG ]; then
|
|
echo "You must have the following enabled in your kernel:" >&2
|
|
cat $TEST_DIR/config >&2
|
|
echo "Resorting to old heuristics" >&2
|
|
fi
|
|
else
|
|
echo "Failed to load configs module, using old heuristics" >&2
|
|
fi
|
|
fi
|
|
}
|
|
|
|
check_setup()
|
|
{
|
|
HAS_FW_LOADER_USER_HELPER="$(kconfig_has CONFIG_FW_LOADER_USER_HELPER=y)"
|
|
HAS_FW_LOADER_USER_HELPER_FALLBACK="$(kconfig_has CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y)"
|
|
HAS_FW_LOADER_COMPRESS_XZ="$(kconfig_has CONFIG_FW_LOADER_COMPRESS_XZ=y)"
|
|
HAS_FW_LOADER_COMPRESS_ZSTD="$(kconfig_has CONFIG_FW_LOADER_COMPRESS_ZSTD=y)"
|
|
HAS_FW_UPLOAD="$(kconfig_has CONFIG_FW_UPLOAD=y)"
|
|
PROC_FW_IGNORE_SYSFS_FALLBACK="0"
|
|
PROC_FW_FORCE_SYSFS_FALLBACK="0"
|
|
|
|
if [ -z $PROC_SYS_DIR ]; then
|
|
PROC_SYS_DIR="/proc/sys/kernel"
|
|
fi
|
|
|
|
FW_PROC="${PROC_SYS_DIR}/firmware_config"
|
|
FW_FORCE_SYSFS_FALLBACK="$FW_PROC/force_sysfs_fallback"
|
|
FW_IGNORE_SYSFS_FALLBACK="$FW_PROC/ignore_sysfs_fallback"
|
|
|
|
if [ -f $FW_FORCE_SYSFS_FALLBACK ]; then
|
|
PROC_FW_FORCE_SYSFS_FALLBACK="$(cat $FW_FORCE_SYSFS_FALLBACK)"
|
|
fi
|
|
|
|
if [ -f $FW_IGNORE_SYSFS_FALLBACK ]; then
|
|
PROC_FW_IGNORE_SYSFS_FALLBACK="$(cat $FW_IGNORE_SYSFS_FALLBACK)"
|
|
fi
|
|
|
|
if [ "$PROC_FW_FORCE_SYSFS_FALLBACK" = "1" ]; then
|
|
HAS_FW_LOADER_USER_HELPER="yes"
|
|
HAS_FW_LOADER_USER_HELPER_FALLBACK="yes"
|
|
fi
|
|
|
|
if [ "$PROC_FW_IGNORE_SYSFS_FALLBACK" = "1" ]; then
|
|
HAS_FW_LOADER_USER_HELPER_FALLBACK="no"
|
|
HAS_FW_LOADER_USER_HELPER="no"
|
|
fi
|
|
|
|
if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
|
|
OLD_TIMEOUT="$(cat /sys/class/firmware/timeout)"
|
|
fi
|
|
|
|
OLD_FWPATH="$(cat /sys/module/firmware_class/parameters/path)"
|
|
|
|
if [ "$HAS_FW_LOADER_COMPRESS_XZ" = "yes" ]; then
|
|
if ! which xz 2> /dev/null > /dev/null; then
|
|
HAS_FW_LOADER_COMPRESS_XZ=""
|
|
fi
|
|
fi
|
|
if [ "$HAS_FW_LOADER_COMPRESS_ZSTD" = "yes" ]; then
|
|
if ! which zstd 2> /dev/null > /dev/null; then
|
|
HAS_FW_LOADER_COMPRESS_ZSTD=""
|
|
fi
|
|
fi
|
|
}
|
|
|
|
verify_reqs()
|
|
{
|
|
if [ "$TEST_REQS_FW_SYSFS_FALLBACK" = "yes" ]; then
|
|
if [ ! "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
|
|
echo "usermode helper disabled so ignoring test"
|
|
exit 0
|
|
fi
|
|
fi
|
|
if [ "$TEST_REQS_FW_UPLOAD" = "yes" ]; then
|
|
if [ ! "$HAS_FW_UPLOAD" = "yes" ]; then
|
|
echo "firmware upload disabled so ignoring test"
|
|
exit 0
|
|
fi
|
|
fi
|
|
}
|
|
|
|
setup_tmp_file()
|
|
{
|
|
FWPATH=$(mktemp -d)
|
|
FW="$FWPATH/test-firmware.bin"
|
|
echo "ABCD0123" >"$FW"
|
|
FW_INTO_BUF="$FWPATH/$TEST_FIRMWARE_INTO_BUF_FILENAME"
|
|
echo "EFGH4567" >"$FW_INTO_BUF"
|
|
NAME=$(basename "$FW")
|
|
if [ "$TEST_REQS_FW_SET_CUSTOM_PATH" = "yes" ]; then
|
|
echo -n "$FWPATH" >/sys/module/firmware_class/parameters/path
|
|
fi
|
|
}
|
|
|
|
__setup_random_file()
|
|
{
|
|
RANDOM_FILE_PATH="$(mktemp -p $FWPATH)"
|
|
# mktemp says dry-run -n is unsafe, so...
|
|
if [[ "$1" = "fake" ]]; then
|
|
rm -rf $RANDOM_FILE_PATH
|
|
sync
|
|
else
|
|
echo "ABCD0123" >"$RANDOM_FILE_PATH"
|
|
fi
|
|
echo $RANDOM_FILE_PATH
|
|
}
|
|
|
|
setup_random_file()
|
|
{
|
|
echo $(__setup_random_file)
|
|
}
|
|
|
|
setup_random_file_fake()
|
|
{
|
|
echo $(__setup_random_file fake)
|
|
}
|
|
|
|
proc_set_force_sysfs_fallback()
|
|
{
|
|
if [ -f $FW_FORCE_SYSFS_FALLBACK ]; then
|
|
echo -n $1 > $FW_FORCE_SYSFS_FALLBACK
|
|
check_setup
|
|
fi
|
|
}
|
|
|
|
proc_set_ignore_sysfs_fallback()
|
|
{
|
|
if [ -f $FW_IGNORE_SYSFS_FALLBACK ]; then
|
|
echo -n $1 > $FW_IGNORE_SYSFS_FALLBACK
|
|
check_setup
|
|
fi
|
|
}
|
|
|
|
proc_restore_defaults()
|
|
{
|
|
proc_set_force_sysfs_fallback 0
|
|
proc_set_ignore_sysfs_fallback 0
|
|
}
|
|
|
|
test_finish()
|
|
{
|
|
if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
|
|
echo "$OLD_TIMEOUT" >/sys/class/firmware/timeout
|
|
fi
|
|
if [ "$TEST_REQS_FW_SET_CUSTOM_PATH" = "yes" ]; then
|
|
if [ "$OLD_FWPATH" = "" ]; then
|
|
# A zero-length write won't work; write a null byte
|
|
printf '\000' >/sys/module/firmware_class/parameters/path
|
|
else
|
|
echo -n "$OLD_FWPATH" >/sys/module/firmware_class/parameters/path
|
|
fi
|
|
fi
|
|
if [ -f $FW ]; then
|
|
rm -f "$FW"
|
|
fi
|
|
if [ -f $FW_INTO_BUF ]; then
|
|
rm -f "$FW_INTO_BUF"
|
|
fi
|
|
if [ -d $FWPATH ]; then
|
|
rm -rf "$FWPATH"
|
|
fi
|
|
proc_restore_defaults
|
|
}
|
|
|
|
kconfig_has()
|
|
{
|
|
if [ -f $PROC_CONFIG ]; then
|
|
if zgrep -q $1 $PROC_CONFIG 2>/dev/null; then
|
|
echo "yes"
|
|
else
|
|
echo "no"
|
|
fi
|
|
else
|
|
# We currently don't have easy heuristics to infer this
|
|
# so best we can do is just try to use the kernel assuming
|
|
# you had enabled it. This matches the old behaviour.
|
|
if [ "$1" = "CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y" ]; then
|
|
echo "yes"
|
|
elif [ "$1" = "CONFIG_FW_LOADER_USER_HELPER=y" ]; then
|
|
if [ -d /sys/class/firmware/ ]; then
|
|
echo yes
|
|
else
|
|
echo no
|
|
fi
|
|
fi
|
|
fi
|
|
}
|