1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3 4# Library of helpers for test scripts. 5set -e 6 7DIR=/sys/devices/virtual/misc/test_firmware 8 9PROC_CONFIG="/proc/config.gz" 10TEST_DIR=$(dirname $0) 11 12# We need to load a different file to test request_firmware_into_buf 13# I believe the issue is firmware loaded cached vs. non-cached 14# with same filename is bungled. 15# To reproduce rename this to test-firmware.bin 16TEST_FIRMWARE_INTO_BUF_FILENAME=test-firmware-into-buf.bin 17 18# Kselftest framework requirement - SKIP code is 4. 19ksft_skip=4 20 21print_reqs_exit() 22{ 23 echo "You must have the following enabled in your kernel:" >&2 24 cat $TEST_DIR/config >&2 25 exit $ksft_skip 26} 27 28test_modprobe() 29{ 30 if [ ! -d $DIR ]; then 31 print_reqs_exit 32 fi 33} 34 35check_mods() 36{ 37 local uid=$(id -u) 38 if [ $uid -ne 0 ]; then 39 echo "skip all tests: must be run as root" >&2 40 exit $ksft_skip 41 fi 42 43 trap "test_modprobe" EXIT 44 if [ ! -d $DIR ]; then 45 modprobe test_firmware 46 fi 47 if [ ! -f $PROC_CONFIG ]; then 48 if modprobe configs 2>/dev/null; then 49 echo "Loaded configs module" 50 if [ ! -f $PROC_CONFIG ]; then 51 echo "You must have the following enabled in your kernel:" >&2 52 cat $TEST_DIR/config >&2 53 echo "Resorting to old heuristics" >&2 54 fi 55 else 56 echo "Failed to load configs module, using old heuristics" >&2 57 fi 58 fi 59} 60 61check_setup() 62{ 63 HAS_FW_LOADER_USER_HELPER="$(kconfig_has CONFIG_FW_LOADER_USER_HELPER=y)" 64 HAS_FW_LOADER_USER_HELPER_FALLBACK="$(kconfig_has CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y)" 65 HAS_FW_LOADER_COMPRESS="$(kconfig_has CONFIG_FW_LOADER_COMPRESS=y)" 66 PROC_FW_IGNORE_SYSFS_FALLBACK="0" 67 PROC_FW_FORCE_SYSFS_FALLBACK="0" 68 69 if [ -z $PROC_SYS_DIR ]; then 70 PROC_SYS_DIR="/proc/sys/kernel" 71 fi 72 73 FW_PROC="${PROC_SYS_DIR}/firmware_config" 74 FW_FORCE_SYSFS_FALLBACK="$FW_PROC/force_sysfs_fallback" 75 FW_IGNORE_SYSFS_FALLBACK="$FW_PROC/ignore_sysfs_fallback" 76 77 if [ -f $FW_FORCE_SYSFS_FALLBACK ]; then 78 PROC_FW_FORCE_SYSFS_FALLBACK="$(cat $FW_FORCE_SYSFS_FALLBACK)" 79 fi 80 81 if [ -f $FW_IGNORE_SYSFS_FALLBACK ]; then 82 PROC_FW_IGNORE_SYSFS_FALLBACK="$(cat $FW_IGNORE_SYSFS_FALLBACK)" 83 fi 84 85 if [ "$PROC_FW_FORCE_SYSFS_FALLBACK" = "1" ]; then 86 HAS_FW_LOADER_USER_HELPER="yes" 87 HAS_FW_LOADER_USER_HELPER_FALLBACK="yes" 88 fi 89 90 if [ "$PROC_FW_IGNORE_SYSFS_FALLBACK" = "1" ]; then 91 HAS_FW_LOADER_USER_HELPER_FALLBACK="no" 92 HAS_FW_LOADER_USER_HELPER="no" 93 fi 94 95 if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then 96 OLD_TIMEOUT="$(cat /sys/class/firmware/timeout)" 97 fi 98 99 OLD_FWPATH="$(cat /sys/module/firmware_class/parameters/path)" 100 101 if [ "$HAS_FW_LOADER_COMPRESS" = "yes" ]; then 102 if ! which xz 2> /dev/null > /dev/null; then 103 HAS_FW_LOADER_COMPRESS="" 104 fi 105 fi 106} 107 108verify_reqs() 109{ 110 if [ "$TEST_REQS_FW_SYSFS_FALLBACK" = "yes" ]; then 111 if [ ! "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then 112 echo "usermode helper disabled so ignoring test" 113 exit 0 114 fi 115 fi 116} 117 118setup_tmp_file() 119{ 120 FWPATH=$(mktemp -d) 121 FW="$FWPATH/test-firmware.bin" 122 echo "ABCD0123" >"$FW" 123 FW_INTO_BUF="$FWPATH/$TEST_FIRMWARE_INTO_BUF_FILENAME" 124 echo "EFGH4567" >"$FW_INTO_BUF" 125 NAME=$(basename "$FW") 126 if [ "$TEST_REQS_FW_SET_CUSTOM_PATH" = "yes" ]; then 127 echo -n "$FWPATH" >/sys/module/firmware_class/parameters/path 128 fi 129} 130 131__setup_random_file() 132{ 133 RANDOM_FILE_PATH="$(mktemp -p $FWPATH)" 134 # mktemp says dry-run -n is unsafe, so... 135 if [[ "$1" = "fake" ]]; then 136 rm -rf $RANDOM_FILE_PATH 137 sync 138 else 139 echo "ABCD0123" >"$RANDOM_FILE_PATH" 140 fi 141 echo $RANDOM_FILE_PATH 142} 143 144setup_random_file() 145{ 146 echo $(__setup_random_file) 147} 148 149setup_random_file_fake() 150{ 151 echo $(__setup_random_file fake) 152} 153 154proc_set_force_sysfs_fallback() 155{ 156 if [ -f $FW_FORCE_SYSFS_FALLBACK ]; then 157 echo -n $1 > $FW_FORCE_SYSFS_FALLBACK 158 check_setup 159 fi 160} 161 162proc_set_ignore_sysfs_fallback() 163{ 164 if [ -f $FW_IGNORE_SYSFS_FALLBACK ]; then 165 echo -n $1 > $FW_IGNORE_SYSFS_FALLBACK 166 check_setup 167 fi 168} 169 170proc_restore_defaults() 171{ 172 proc_set_force_sysfs_fallback 0 173 proc_set_ignore_sysfs_fallback 0 174} 175 176test_finish() 177{ 178 if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then 179 echo "$OLD_TIMEOUT" >/sys/class/firmware/timeout 180 fi 181 if [ "$TEST_REQS_FW_SET_CUSTOM_PATH" = "yes" ]; then 182 if [ "$OLD_FWPATH" = "" ]; then 183 # A zero-length write won't work; write a null byte 184 printf '\000' >/sys/module/firmware_class/parameters/path 185 else 186 echo -n "$OLD_FWPATH" >/sys/module/firmware_class/parameters/path 187 fi 188 fi 189 if [ -f $FW ]; then 190 rm -f "$FW" 191 fi 192 if [ -f $FW_INTO_BUF ]; then 193 rm -f "$FW_INTO_BUF" 194 fi 195 if [ -d $FWPATH ]; then 196 rm -rf "$FWPATH" 197 fi 198 proc_restore_defaults 199} 200 201kconfig_has() 202{ 203 if [ -f $PROC_CONFIG ]; then 204 if zgrep -q $1 $PROC_CONFIG 2>/dev/null; then 205 echo "yes" 206 else 207 echo "no" 208 fi 209 else 210 # We currently don't have easy heuristics to infer this 211 # so best we can do is just try to use the kernel assuming 212 # you had enabled it. This matches the old behaviour. 213 if [ "$1" = "CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y" ]; then 214 echo "yes" 215 elif [ "$1" = "CONFIG_FW_LOADER_USER_HELPER=y" ]; then 216 if [ -d /sys/class/firmware/ ]; then 217 echo yes 218 else 219 echo no 220 fi 221 fi 222 fi 223} 224