fw_filesystem.sh 9.28 KB
Newer Older
1
#!/bin/bash
2
# SPDX-License-Identifier: GPL-2.0
3 4 5 6 7 8
# This validates that the kernel will load firmware out of its list of
# firmware locations on disk. Since the user helper does similar work,
# we reset the custom load directory to a location the user helper doesn't
# know so we can be sure we're not accidentally testing the user helper.
set -e

9 10
TEST_REQS_FW_SYSFS_FALLBACK="no"
TEST_REQS_FW_SET_CUSTOM_PATH="yes"
11
TEST_DIR=$(dirname $0)
12
source $TEST_DIR/fw_lib.sh
13

14
check_mods
15 16 17
check_setup
verify_reqs
setup_tmp_file
18 19 20

trap "test_finish" EXIT

21 22 23 24 25
if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
	# Turn down the timeout so failures don't take so long.
	echo 1 >/sys/class/firmware/timeout
fi

26
if printf '\000' >"$DIR"/trigger_request 2> /dev/null; then
27 28 29 30
	echo "$0: empty filename should not succeed" >&2
	exit 1
fi

31 32
if [ ! -e "$DIR"/trigger_async_request ]; then
	echo "$0: empty filename: async trigger not present, ignoring test" >&2
33
	exit $ksft_skip
34 35 36 37 38
else
	if printf '\000' >"$DIR"/trigger_async_request 2> /dev/null; then
		echo "$0: empty filename should not succeed (async)" >&2
		exit 1
	fi
39 40
fi

41
# Request a firmware that doesn't exist, it should fail.
42
if echo -n "nope-$NAME" >"$DIR"/trigger_request 2> /dev/null; then
43 44 45
	echo "$0: firmware shouldn't have loaded" >&2
	exit 1
fi
46 47 48 49
if diff -q "$FW" /dev/test_firmware >/dev/null ; then
	echo "$0: firmware was not expected to match" >&2
	exit 1
else
50 51 52
	if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
		echo "$0: timeout works"
	fi
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
fi

# This should succeed via kernel load or will fail after 1 second after
# being handed over to the user helper, which won't find the fw either.
if ! echo -n "$NAME" >"$DIR"/trigger_request ; then
	echo "$0: could not trigger request" >&2
	exit 1
fi

# Verify the contents are what we expect.
if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
	echo "$0: firmware was not loaded" >&2
	exit 1
else
	echo "$0: filesystem loading works"
fi

70
# Try the asynchronous version too
71 72
if [ ! -e "$DIR"/trigger_async_request ]; then
	echo "$0: firmware loading: async trigger not present, ignoring test" >&2
73
	exit $ksft_skip
74
else
75 76 77 78 79 80 81 82 83 84 85 86
	if ! echo -n "$NAME" >"$DIR"/trigger_async_request ; then
		echo "$0: could not trigger async request" >&2
		exit 1
	fi

	# Verify the contents are what we expect.
	if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
		echo "$0: firmware was not loaded (async)" >&2
		exit 1
	else
		echo "$0: async filesystem loading works"
	fi
87 88
fi

89 90 91 92 93
### Batched requests tests
test_config_present()
{
	if [ ! -f $DIR/reset ]; then
		echo "Configuration triggers not present, ignoring test"
94
		exit $ksft_skip
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
	fi
}

# Defaults :
#
# send_uevent: 1
# sync_direct: 0
# name: test-firmware.bin
# num_requests: 4
config_reset()
{
	echo 1 >  $DIR/reset
}

release_all_firmware()
{
	echo 1 >  $DIR/release_all_firmware
}

config_set_name()
{
	echo -n $1 >  $DIR/config_name
}

119 120 121 122 123 124 125 126 127 128
config_set_into_buf()
{
	echo 1 >  $DIR/config_into_buf
}

config_unset_into_buf()
{
	echo 0 >  $DIR/config_into_buf
}

129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
config_set_sync_direct()
{
	echo 1 >  $DIR/config_sync_direct
}

config_unset_sync_direct()
{
	echo 0 >  $DIR/config_sync_direct
}

config_set_uevent()
{
	echo 1 >  $DIR/config_send_uevent
}

config_unset_uevent()
{
	echo 0 >  $DIR/config_send_uevent
}

config_trigger_sync()
{
	echo -n 1 > $DIR/trigger_batched_requests 2>/dev/null
}

config_trigger_async()
{
	echo -n 1 > $DIR/trigger_batched_requests_async 2> /dev/null
}

config_set_read_fw_idx()
{
	echo -n $1 > $DIR/config_read_fw_idx 2> /dev/null
}

read_firmwares()
{
166 167
	if [ "$(cat $DIR/config_into_buf)" == "1" ]; then
		fwfile="$FW_INTO_BUF"
168 169 170
	else
		fwfile="$FW"
	fi
171 172 173
	if [ "$1" = "xzonly" ]; then
		fwfile="${fwfile}-orig"
	fi
174 175
	for i in $(seq 0 3); do
		config_set_read_fw_idx $i
176 177 178 179
		# Verify the contents are what we expect.
		# -Z required for now -- check for yourself, md5sum
		# on $FW and DIR/read_firmware will yield the same. Even
		# cmp agrees, so something is off.
180
		if ! diff -q -Z "$fwfile" $DIR/read_firmware 2>/dev/null ; then
181 182 183 184 185 186 187 188 189 190 191
			echo "request #$i: firmware was not loaded" >&2
			exit 1
		fi
	done
}

read_firmwares_expect_nofile()
{
	for i in $(seq 0 3); do
		config_set_read_fw_idx $i
		# Ensures contents differ
192
		if diff -q -Z "$FW" $DIR/read_firmware 2>/dev/null ; then
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
			echo "request $i: file was not expected to match" >&2
			exit 1
		fi
	done
}

test_batched_request_firmware_nofile()
{
	echo -n "Batched request_firmware() nofile try #$1: "
	config_reset
	config_set_name nope-test-firmware.bin
	config_trigger_sync
	read_firmwares_expect_nofile
	release_all_firmware
	echo "OK"
}

210 211 212 213 214 215 216 217 218 219 220 221
test_batched_request_firmware_into_buf_nofile()
{
	echo -n "Batched request_firmware_into_buf() nofile try #$1: "
	config_reset
	config_set_name nope-test-firmware.bin
	config_set_into_buf
	config_trigger_sync
	read_firmwares_expect_nofile
	release_all_firmware
	echo "OK"
}

222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
test_batched_request_firmware_direct_nofile()
{
	echo -n "Batched request_firmware_direct() nofile try #$1: "
	config_reset
	config_set_name nope-test-firmware.bin
	config_set_sync_direct
	config_trigger_sync
	release_all_firmware
	echo "OK"
}

test_request_firmware_nowait_uevent_nofile()
{
	echo -n "Batched request_firmware_nowait(uevent=true) nofile try #$1: "
	config_reset
	config_set_name nope-test-firmware.bin
	config_trigger_async
	release_all_firmware
	echo "OK"
}

test_wait_and_cancel_custom_load()
{
	if [ "$HAS_FW_LOADER_USER_HELPER" != "yes" ]; then
		return
	fi
	local timeout=10
	name=$1
	while [ ! -e "$DIR"/"$name"/loading ]; do
		sleep 0.1
		timeout=$(( $timeout - 1 ))
		if [ "$timeout" -eq 0 ]; then
			echo "firmware interface never appeared:" >&2
			echo "$DIR/$name/loading" >&2
			exit 1
		fi
	done
	echo -1 >"$DIR"/"$name"/loading
}

test_request_firmware_nowait_custom_nofile()
{
	echo -n "Batched request_firmware_nowait(uevent=false) nofile try #$1: "
265
	config_reset
266
	config_unset_uevent
267 268 269
	RANDOM_FILE_PATH=$(setup_random_file_fake)
	RANDOM_FILE="$(basename $RANDOM_FILE_PATH)"
	config_set_name $RANDOM_FILE
270
	config_trigger_async &
271
	test_wait_and_cancel_custom_load $RANDOM_FILE
272 273 274 275 276 277 278
	wait
	release_all_firmware
	echo "OK"
}

test_batched_request_firmware()
{
279
	echo -n "Batched request_firmware() $2 try #$1: "
280 281
	config_reset
	config_trigger_sync
282
	read_firmwares $2
283 284 285 286
	release_all_firmware
	echo "OK"
}

287 288 289 290 291 292 293 294 295 296 297 298
test_batched_request_firmware_into_buf()
{
	echo -n "Batched request_firmware_into_buf() $2 try #$1: "
	config_reset
	config_set_name $TEST_FIRMWARE_INTO_BUF_FILENAME
	config_set_into_buf
	config_trigger_sync
	read_firmwares $2
	release_all_firmware
	echo "OK"
}

299 300
test_batched_request_firmware_direct()
{
301
	echo -n "Batched request_firmware_direct() $2 try #$1: "
302 303 304 305 306 307 308 309 310
	config_reset
	config_set_sync_direct
	config_trigger_sync
	release_all_firmware
	echo "OK"
}

test_request_firmware_nowait_uevent()
{
311
	echo -n "Batched request_firmware_nowait(uevent=true) $2 try #$1: "
312 313 314 315 316 317 318 319
	config_reset
	config_trigger_async
	release_all_firmware
	echo "OK"
}

test_request_firmware_nowait_custom()
{
320
	echo -n "Batched request_firmware_nowait(uevent=false) $2 try #$1: "
321
	config_reset
322
	config_unset_uevent
323 324
	RANDOM_FILE_PATH=$(setup_random_file)
	RANDOM_FILE="$(basename $RANDOM_FILE_PATH)"
325 326 327 328 329
	if [ "$2" = "both" ]; then
		xz -9 -C crc32 -k $RANDOM_FILE_PATH
	elif [ "$2" = "xzonly" ]; then
		xz -9 -C crc32 $RANDOM_FILE_PATH
	fi
330
	config_set_name $RANDOM_FILE
331 332 333 334 335 336 337 338 339 340 341 342 343
	config_trigger_async
	release_all_firmware
	echo "OK"
}

# Only continue if batched request triggers are present on the
# test-firmware driver
test_config_present

# test with the file present
echo
echo "Testing with the file present..."
for i in $(seq 1 5); do
344
	test_batched_request_firmware $i normal
345 346
done

347 348 349 350
for i in $(seq 1 5); do
	test_batched_request_firmware_into_buf $i normal
done

351
for i in $(seq 1 5); do
352
	test_batched_request_firmware_direct $i normal
353 354 355
done

for i in $(seq 1 5); do
356
	test_request_firmware_nowait_uevent $i normal
357 358 359
done

for i in $(seq 1 5); do
360
	test_request_firmware_nowait_custom $i normal
361 362 363 364 365 366 367 368 369 370
done

# Test for file not found, errors are expected, the failure would be
# a hung task, which would require a hard reset.
echo
echo "Testing with the file missing..."
for i in $(seq 1 5); do
	test_batched_request_firmware_nofile $i
done

371 372 373 374
for i in $(seq 1 5); do
	test_batched_request_firmware_into_buf_nofile $i
done

375 376 377 378 379 380 381 382 383 384 385 386
for i in $(seq 1 5); do
	test_batched_request_firmware_direct_nofile $i
done

for i in $(seq 1 5); do
	test_request_firmware_nowait_uevent_nofile $i
done

for i in $(seq 1 5); do
	test_request_firmware_nowait_custom_nofile $i
done

387 388 389 390 391 392 393 394 395 396 397
test "$HAS_FW_LOADER_COMPRESS" != "yes" && exit 0

# test with both files present
xz -9 -C crc32 -k $FW
config_set_name $NAME
echo
echo "Testing with both plain and xz files present..."
for i in $(seq 1 5); do
	test_batched_request_firmware $i both
done

398 399 400 401
for i in $(seq 1 5); do
	test_batched_request_firmware_into_buf $i both
done

402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421
for i in $(seq 1 5); do
	test_batched_request_firmware_direct $i both
done

for i in $(seq 1 5); do
	test_request_firmware_nowait_uevent $i both
done

for i in $(seq 1 5); do
	test_request_firmware_nowait_custom $i both
done

# test with only xz file present
mv "$FW" "${FW}-orig"
echo
echo "Testing with only xz file present..."
for i in $(seq 1 5); do
	test_batched_request_firmware $i xzonly
done

422 423 424 425
for i in $(seq 1 5); do
	test_batched_request_firmware_into_buf $i xzonly
done

426 427 428 429 430 431 432 433 434 435 436 437
for i in $(seq 1 5); do
	test_batched_request_firmware_direct $i xzonly
done

for i in $(seq 1 5); do
	test_request_firmware_nowait_uevent $i xzonly
done

for i in $(seq 1 5); do
	test_request_firmware_nowait_custom $i xzonly
done

438
exit 0