18c2ecf20Sopenharmony_ci#!/bin/bash
28c2ecf20Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci# Library of helpers for test scripts.
58c2ecf20Sopenharmony_ciset -e
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ciDIR=/sys/devices/virtual/misc/test_firmware
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ciPROC_CONFIG="/proc/config.gz"
108c2ecf20Sopenharmony_ciTEST_DIR=$(dirname $0)
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci# We need to load a different file to test request_firmware_into_buf
138c2ecf20Sopenharmony_ci# I believe the issue is firmware loaded cached vs. non-cached
148c2ecf20Sopenharmony_ci# with same filename is bungled.
158c2ecf20Sopenharmony_ci# To reproduce rename this to test-firmware.bin
168c2ecf20Sopenharmony_ciTEST_FIRMWARE_INTO_BUF_FILENAME=test-firmware-into-buf.bin
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci# Kselftest framework requirement - SKIP code is 4.
198c2ecf20Sopenharmony_ciksft_skip=4
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ciprint_reqs_exit()
228c2ecf20Sopenharmony_ci{
238c2ecf20Sopenharmony_ci	echo "You must have the following enabled in your kernel:" >&2
248c2ecf20Sopenharmony_ci	cat $TEST_DIR/config >&2
258c2ecf20Sopenharmony_ci	exit $ksft_skip
268c2ecf20Sopenharmony_ci}
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_citest_modprobe()
298c2ecf20Sopenharmony_ci{
308c2ecf20Sopenharmony_ci	if [ ! -d $DIR ]; then
318c2ecf20Sopenharmony_ci		print_reqs_exit
328c2ecf20Sopenharmony_ci	fi
338c2ecf20Sopenharmony_ci}
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_cicheck_mods()
368c2ecf20Sopenharmony_ci{
378c2ecf20Sopenharmony_ci	local uid=$(id -u)
388c2ecf20Sopenharmony_ci	if [ $uid -ne 0 ]; then
398c2ecf20Sopenharmony_ci		echo "skip all tests: must be run as root" >&2
408c2ecf20Sopenharmony_ci		exit $ksft_skip
418c2ecf20Sopenharmony_ci	fi
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	trap "test_modprobe" EXIT
448c2ecf20Sopenharmony_ci	if [ ! -d $DIR ]; then
458c2ecf20Sopenharmony_ci		modprobe test_firmware
468c2ecf20Sopenharmony_ci	fi
478c2ecf20Sopenharmony_ci	if [ ! -f $PROC_CONFIG ]; then
488c2ecf20Sopenharmony_ci		if modprobe configs 2>/dev/null; then
498c2ecf20Sopenharmony_ci			echo "Loaded configs module"
508c2ecf20Sopenharmony_ci			if [ ! -f $PROC_CONFIG ]; then
518c2ecf20Sopenharmony_ci				echo "You must have the following enabled in your kernel:" >&2
528c2ecf20Sopenharmony_ci				cat $TEST_DIR/config >&2
538c2ecf20Sopenharmony_ci				echo "Resorting to old heuristics" >&2
548c2ecf20Sopenharmony_ci			fi
558c2ecf20Sopenharmony_ci		else
568c2ecf20Sopenharmony_ci			echo "Failed to load configs module, using old heuristics" >&2
578c2ecf20Sopenharmony_ci		fi
588c2ecf20Sopenharmony_ci	fi
598c2ecf20Sopenharmony_ci}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_cicheck_setup()
628c2ecf20Sopenharmony_ci{
638c2ecf20Sopenharmony_ci	HAS_FW_LOADER_USER_HELPER="$(kconfig_has CONFIG_FW_LOADER_USER_HELPER=y)"
648c2ecf20Sopenharmony_ci	HAS_FW_LOADER_USER_HELPER_FALLBACK="$(kconfig_has CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y)"
658c2ecf20Sopenharmony_ci	HAS_FW_LOADER_COMPRESS="$(kconfig_has CONFIG_FW_LOADER_COMPRESS=y)"
668c2ecf20Sopenharmony_ci	PROC_FW_IGNORE_SYSFS_FALLBACK="0"
678c2ecf20Sopenharmony_ci	PROC_FW_FORCE_SYSFS_FALLBACK="0"
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	if [ -z $PROC_SYS_DIR ]; then
708c2ecf20Sopenharmony_ci		PROC_SYS_DIR="/proc/sys/kernel"
718c2ecf20Sopenharmony_ci	fi
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	FW_PROC="${PROC_SYS_DIR}/firmware_config"
748c2ecf20Sopenharmony_ci	FW_FORCE_SYSFS_FALLBACK="$FW_PROC/force_sysfs_fallback"
758c2ecf20Sopenharmony_ci	FW_IGNORE_SYSFS_FALLBACK="$FW_PROC/ignore_sysfs_fallback"
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	if [ -f $FW_FORCE_SYSFS_FALLBACK ]; then
788c2ecf20Sopenharmony_ci		PROC_FW_FORCE_SYSFS_FALLBACK="$(cat $FW_FORCE_SYSFS_FALLBACK)"
798c2ecf20Sopenharmony_ci	fi
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	if [ -f $FW_IGNORE_SYSFS_FALLBACK ]; then
828c2ecf20Sopenharmony_ci		PROC_FW_IGNORE_SYSFS_FALLBACK="$(cat $FW_IGNORE_SYSFS_FALLBACK)"
838c2ecf20Sopenharmony_ci	fi
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	if [ "$PROC_FW_FORCE_SYSFS_FALLBACK" = "1" ]; then
868c2ecf20Sopenharmony_ci		HAS_FW_LOADER_USER_HELPER="yes"
878c2ecf20Sopenharmony_ci		HAS_FW_LOADER_USER_HELPER_FALLBACK="yes"
888c2ecf20Sopenharmony_ci	fi
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	if [ "$PROC_FW_IGNORE_SYSFS_FALLBACK" = "1" ]; then
918c2ecf20Sopenharmony_ci		HAS_FW_LOADER_USER_HELPER_FALLBACK="no"
928c2ecf20Sopenharmony_ci		HAS_FW_LOADER_USER_HELPER="no"
938c2ecf20Sopenharmony_ci	fi
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
968c2ecf20Sopenharmony_ci	       OLD_TIMEOUT="$(cat /sys/class/firmware/timeout)"
978c2ecf20Sopenharmony_ci	fi
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	OLD_FWPATH="$(cat /sys/module/firmware_class/parameters/path)"
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	if [ "$HAS_FW_LOADER_COMPRESS" = "yes" ]; then
1028c2ecf20Sopenharmony_ci		if ! which xz 2> /dev/null > /dev/null; then
1038c2ecf20Sopenharmony_ci			HAS_FW_LOADER_COMPRESS=""
1048c2ecf20Sopenharmony_ci		fi
1058c2ecf20Sopenharmony_ci	fi
1068c2ecf20Sopenharmony_ci}
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_civerify_reqs()
1098c2ecf20Sopenharmony_ci{
1108c2ecf20Sopenharmony_ci	if [ "$TEST_REQS_FW_SYSFS_FALLBACK" = "yes" ]; then
1118c2ecf20Sopenharmony_ci		if [ ! "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
1128c2ecf20Sopenharmony_ci			echo "usermode helper disabled so ignoring test"
1138c2ecf20Sopenharmony_ci			exit 0
1148c2ecf20Sopenharmony_ci		fi
1158c2ecf20Sopenharmony_ci	fi
1168c2ecf20Sopenharmony_ci}
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_cisetup_tmp_file()
1198c2ecf20Sopenharmony_ci{
1208c2ecf20Sopenharmony_ci	FWPATH=$(mktemp -d)
1218c2ecf20Sopenharmony_ci	FW="$FWPATH/test-firmware.bin"
1228c2ecf20Sopenharmony_ci	echo "ABCD0123" >"$FW"
1238c2ecf20Sopenharmony_ci	FW_INTO_BUF="$FWPATH/$TEST_FIRMWARE_INTO_BUF_FILENAME"
1248c2ecf20Sopenharmony_ci	echo "EFGH4567" >"$FW_INTO_BUF"
1258c2ecf20Sopenharmony_ci	NAME=$(basename "$FW")
1268c2ecf20Sopenharmony_ci	if [ "$TEST_REQS_FW_SET_CUSTOM_PATH" = "yes" ]; then
1278c2ecf20Sopenharmony_ci		echo -n "$FWPATH" >/sys/module/firmware_class/parameters/path
1288c2ecf20Sopenharmony_ci	fi
1298c2ecf20Sopenharmony_ci}
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci__setup_random_file()
1328c2ecf20Sopenharmony_ci{
1338c2ecf20Sopenharmony_ci	RANDOM_FILE_PATH="$(mktemp -p $FWPATH)"
1348c2ecf20Sopenharmony_ci	# mktemp says dry-run -n is unsafe, so...
1358c2ecf20Sopenharmony_ci	if [[ "$1" = "fake" ]]; then
1368c2ecf20Sopenharmony_ci		rm -rf $RANDOM_FILE_PATH
1378c2ecf20Sopenharmony_ci		sync
1388c2ecf20Sopenharmony_ci	else
1398c2ecf20Sopenharmony_ci		echo "ABCD0123" >"$RANDOM_FILE_PATH"
1408c2ecf20Sopenharmony_ci	fi
1418c2ecf20Sopenharmony_ci	echo $RANDOM_FILE_PATH
1428c2ecf20Sopenharmony_ci}
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_cisetup_random_file()
1458c2ecf20Sopenharmony_ci{
1468c2ecf20Sopenharmony_ci	echo $(__setup_random_file)
1478c2ecf20Sopenharmony_ci}
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_cisetup_random_file_fake()
1508c2ecf20Sopenharmony_ci{
1518c2ecf20Sopenharmony_ci	echo $(__setup_random_file fake)
1528c2ecf20Sopenharmony_ci}
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ciproc_set_force_sysfs_fallback()
1558c2ecf20Sopenharmony_ci{
1568c2ecf20Sopenharmony_ci	if [ -f $FW_FORCE_SYSFS_FALLBACK ]; then
1578c2ecf20Sopenharmony_ci		echo -n $1 > $FW_FORCE_SYSFS_FALLBACK
1588c2ecf20Sopenharmony_ci		check_setup
1598c2ecf20Sopenharmony_ci	fi
1608c2ecf20Sopenharmony_ci}
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ciproc_set_ignore_sysfs_fallback()
1638c2ecf20Sopenharmony_ci{
1648c2ecf20Sopenharmony_ci	if [ -f $FW_IGNORE_SYSFS_FALLBACK ]; then
1658c2ecf20Sopenharmony_ci		echo -n $1 > $FW_IGNORE_SYSFS_FALLBACK
1668c2ecf20Sopenharmony_ci		check_setup
1678c2ecf20Sopenharmony_ci	fi
1688c2ecf20Sopenharmony_ci}
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ciproc_restore_defaults()
1718c2ecf20Sopenharmony_ci{
1728c2ecf20Sopenharmony_ci	proc_set_force_sysfs_fallback 0
1738c2ecf20Sopenharmony_ci	proc_set_ignore_sysfs_fallback 0
1748c2ecf20Sopenharmony_ci}
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_citest_finish()
1778c2ecf20Sopenharmony_ci{
1788c2ecf20Sopenharmony_ci	if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
1798c2ecf20Sopenharmony_ci		echo "$OLD_TIMEOUT" >/sys/class/firmware/timeout
1808c2ecf20Sopenharmony_ci	fi
1818c2ecf20Sopenharmony_ci	if [ "$TEST_REQS_FW_SET_CUSTOM_PATH" = "yes" ]; then
1828c2ecf20Sopenharmony_ci		if [ "$OLD_FWPATH" = "" ]; then
1838c2ecf20Sopenharmony_ci			# A zero-length write won't work; write a null byte
1848c2ecf20Sopenharmony_ci			printf '\000' >/sys/module/firmware_class/parameters/path
1858c2ecf20Sopenharmony_ci		else
1868c2ecf20Sopenharmony_ci			echo -n "$OLD_FWPATH" >/sys/module/firmware_class/parameters/path
1878c2ecf20Sopenharmony_ci		fi
1888c2ecf20Sopenharmony_ci	fi
1898c2ecf20Sopenharmony_ci	if [ -f $FW ]; then
1908c2ecf20Sopenharmony_ci		rm -f "$FW"
1918c2ecf20Sopenharmony_ci	fi
1928c2ecf20Sopenharmony_ci	if [ -f $FW_INTO_BUF ]; then
1938c2ecf20Sopenharmony_ci		rm -f "$FW_INTO_BUF"
1948c2ecf20Sopenharmony_ci	fi
1958c2ecf20Sopenharmony_ci	if [ -d $FWPATH ]; then
1968c2ecf20Sopenharmony_ci		rm -rf "$FWPATH"
1978c2ecf20Sopenharmony_ci	fi
1988c2ecf20Sopenharmony_ci	proc_restore_defaults
1998c2ecf20Sopenharmony_ci}
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_cikconfig_has()
2028c2ecf20Sopenharmony_ci{
2038c2ecf20Sopenharmony_ci	if [ -f $PROC_CONFIG ]; then
2048c2ecf20Sopenharmony_ci		if zgrep -q $1 $PROC_CONFIG 2>/dev/null; then
2058c2ecf20Sopenharmony_ci			echo "yes"
2068c2ecf20Sopenharmony_ci		else
2078c2ecf20Sopenharmony_ci			echo "no"
2088c2ecf20Sopenharmony_ci		fi
2098c2ecf20Sopenharmony_ci	else
2108c2ecf20Sopenharmony_ci		# We currently don't have easy heuristics to infer this
2118c2ecf20Sopenharmony_ci		# so best we can do is just try to use the kernel assuming
2128c2ecf20Sopenharmony_ci		# you had enabled it. This matches the old behaviour.
2138c2ecf20Sopenharmony_ci		if [ "$1" = "CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y" ]; then
2148c2ecf20Sopenharmony_ci			echo "yes"
2158c2ecf20Sopenharmony_ci		elif [ "$1" = "CONFIG_FW_LOADER_USER_HELPER=y" ]; then
2168c2ecf20Sopenharmony_ci			if [ -d /sys/class/firmware/ ]; then
2178c2ecf20Sopenharmony_ci				echo yes
2188c2ecf20Sopenharmony_ci			else
2198c2ecf20Sopenharmony_ci				echo no
2208c2ecf20Sopenharmony_ci			fi
2218c2ecf20Sopenharmony_ci		fi
2228c2ecf20Sopenharmony_ci	fi
2238c2ecf20Sopenharmony_ci}
224