162306a36Sopenharmony_ci#!/bin/bash
262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0
362306a36Sopenharmony_ci# This validates the user-initiated fw upload mechanism of the firmware
462306a36Sopenharmony_ci# loader. It verifies that one or more firmware devices can be created
562306a36Sopenharmony_ci# for a device driver. It also verifies the data transfer, the
662306a36Sopenharmony_ci# cancellation support, and the error flows.
762306a36Sopenharmony_ciset -e
862306a36Sopenharmony_ci
962306a36Sopenharmony_ciTEST_REQS_FW_UPLOAD="yes"
1062306a36Sopenharmony_ciTEST_DIR=$(dirname $0)
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ciprogress_states="preparing transferring  programming"
1362306a36Sopenharmony_cierrors="hw-error
1462306a36Sopenharmony_ci	timeout
1562306a36Sopenharmony_ci	device-busy
1662306a36Sopenharmony_ci	invalid-file-size
1762306a36Sopenharmony_ci	read-write-error
1862306a36Sopenharmony_ci	flash-wearout"
1962306a36Sopenharmony_cierror_abort="user-abort"
2062306a36Sopenharmony_cifwname1=fw1
2162306a36Sopenharmony_cifwname2=fw2
2262306a36Sopenharmony_cifwname3=fw3
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_cisource $TEST_DIR/fw_lib.sh
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cicheck_mods
2762306a36Sopenharmony_cicheck_setup
2862306a36Sopenharmony_civerify_reqs
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_citrap "upload_finish" EXIT
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ciupload_finish() {
3362306a36Sopenharmony_ci	local fwdevs="$fwname1 $fwname2 $fwname3"
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	for name in $fwdevs; do
3662306a36Sopenharmony_ci		if [ -e "$DIR/$name" ]; then
3762306a36Sopenharmony_ci			echo -n "$name" > "$DIR"/upload_unregister
3862306a36Sopenharmony_ci		fi
3962306a36Sopenharmony_ci	done
4062306a36Sopenharmony_ci}
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ciupload_fw() {
4362306a36Sopenharmony_ci	local name="$1"
4462306a36Sopenharmony_ci	local file="$2"
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	echo 1 > "$DIR"/"$name"/loading
4762306a36Sopenharmony_ci	cat "$file" > "$DIR"/"$name"/data
4862306a36Sopenharmony_ci	echo 0 > "$DIR"/"$name"/loading
4962306a36Sopenharmony_ci}
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_civerify_fw() {
5262306a36Sopenharmony_ci	local name="$1"
5362306a36Sopenharmony_ci	local file="$2"
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	echo -n "$name" > "$DIR"/config_upload_name
5662306a36Sopenharmony_ci	if ! cmp "$file" "$DIR"/upload_read > /dev/null 2>&1; then
5762306a36Sopenharmony_ci		echo "$0: firmware compare for $name did not match" >&2
5862306a36Sopenharmony_ci		exit 1
5962306a36Sopenharmony_ci	fi
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	echo "$0: firmware upload for $name works" >&2
6262306a36Sopenharmony_ci	return 0
6362306a36Sopenharmony_ci}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ciinject_error() {
6662306a36Sopenharmony_ci	local name="$1"
6762306a36Sopenharmony_ci	local status="$2"
6862306a36Sopenharmony_ci	local error="$3"
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	echo 1 > "$DIR"/"$name"/loading
7162306a36Sopenharmony_ci	echo -n "inject":"$status":"$error" > "$DIR"/"$name"/data
7262306a36Sopenharmony_ci	echo 0 > "$DIR"/"$name"/loading
7362306a36Sopenharmony_ci}
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ciawait_status() {
7662306a36Sopenharmony_ci	local name="$1"
7762306a36Sopenharmony_ci	local expected="$2"
7862306a36Sopenharmony_ci	local status
7962306a36Sopenharmony_ci	local i
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	let i=0
8262306a36Sopenharmony_ci	while [ $i -lt 50 ]; do
8362306a36Sopenharmony_ci		status=$(cat "$DIR"/"$name"/status)
8462306a36Sopenharmony_ci		if [ "$status" = "$expected" ]; then
8562306a36Sopenharmony_ci			return 0;
8662306a36Sopenharmony_ci		fi
8762306a36Sopenharmony_ci		sleep 1e-03
8862306a36Sopenharmony_ci		let i=$i+1
8962306a36Sopenharmony_ci	done
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	echo "$0: Invalid status: Expected $expected, Actual $status" >&2
9262306a36Sopenharmony_ci	return 1;
9362306a36Sopenharmony_ci}
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ciawait_idle() {
9662306a36Sopenharmony_ci	local name="$1"
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	await_status "$name" "idle"
9962306a36Sopenharmony_ci	return $?
10062306a36Sopenharmony_ci}
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ciexpect_error() {
10362306a36Sopenharmony_ci	local name="$1"
10462306a36Sopenharmony_ci	local expected="$2"
10562306a36Sopenharmony_ci	local error=$(cat "$DIR"/"$name"/error)
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	if [ "$error" != "$expected" ]; then
10862306a36Sopenharmony_ci		echo "Invalid error: Expected $expected, Actual $error" >&2
10962306a36Sopenharmony_ci		return 1
11062306a36Sopenharmony_ci	fi
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	return 0
11362306a36Sopenharmony_ci}
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_cirandom_firmware() {
11662306a36Sopenharmony_ci	local bs="$1"
11762306a36Sopenharmony_ci	local count="$2"
11862306a36Sopenharmony_ci	local file=$(mktemp -p /tmp uploadfwXXX.bin)
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	dd if=/dev/urandom of="$file" bs="$bs" count="$count" > /dev/null 2>&1
12162306a36Sopenharmony_ci	echo "$file"
12262306a36Sopenharmony_ci}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_citest_upload_cancel() {
12562306a36Sopenharmony_ci	local name="$1"
12662306a36Sopenharmony_ci	local status
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	for status in $progress_states; do
12962306a36Sopenharmony_ci		inject_error $name $status $error_abort
13062306a36Sopenharmony_ci		if ! await_status $name $status; then
13162306a36Sopenharmony_ci			exit 1
13262306a36Sopenharmony_ci		fi
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci		echo 1 > "$DIR"/"$name"/cancel
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci		if ! await_idle $name; then
13762306a36Sopenharmony_ci			exit 1
13862306a36Sopenharmony_ci		fi
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci		if ! expect_error $name "$status":"$error_abort"; then
14162306a36Sopenharmony_ci			exit 1
14262306a36Sopenharmony_ci		fi
14362306a36Sopenharmony_ci	done
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	echo "$0: firmware upload cancellation works"
14662306a36Sopenharmony_ci	return 0
14762306a36Sopenharmony_ci}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_citest_error_handling() {
15062306a36Sopenharmony_ci	local name=$1
15162306a36Sopenharmony_ci	local status
15262306a36Sopenharmony_ci	local error
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	for status in $progress_states; do
15562306a36Sopenharmony_ci		for error in $errors; do
15662306a36Sopenharmony_ci			inject_error $name $status $error
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci			if ! await_idle $name; then
15962306a36Sopenharmony_ci				exit 1
16062306a36Sopenharmony_ci			fi
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci			if ! expect_error $name "$status":"$error"; then
16362306a36Sopenharmony_ci				exit 1
16462306a36Sopenharmony_ci			fi
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci		done
16762306a36Sopenharmony_ci	done
16862306a36Sopenharmony_ci	echo "$0: firmware upload error handling works"
16962306a36Sopenharmony_ci}
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_citest_fw_too_big() {
17262306a36Sopenharmony_ci	local name=$1
17362306a36Sopenharmony_ci	local fw_too_big=`random_firmware 512 5`
17462306a36Sopenharmony_ci	local expected="preparing:invalid-file-size"
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	upload_fw $name $fw_too_big
17762306a36Sopenharmony_ci	rm -f $fw_too_big
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	if ! await_idle $name; then
18062306a36Sopenharmony_ci		exit 1
18162306a36Sopenharmony_ci	fi
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	if ! expect_error $name $expected; then
18462306a36Sopenharmony_ci		exit 1
18562306a36Sopenharmony_ci	fi
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	echo "$0: oversized firmware error handling works"
18862306a36Sopenharmony_ci}
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ciecho -n "$fwname1" > "$DIR"/upload_register
19162306a36Sopenharmony_ciecho -n "$fwname2" > "$DIR"/upload_register
19262306a36Sopenharmony_ciecho -n "$fwname3" > "$DIR"/upload_register
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_citest_upload_cancel $fwname1
19562306a36Sopenharmony_citest_error_handling $fwname1
19662306a36Sopenharmony_citest_fw_too_big $fwname1
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_cifw_file1=`random_firmware 512 4`
19962306a36Sopenharmony_cifw_file2=`random_firmware 512 3`
20062306a36Sopenharmony_cifw_file3=`random_firmware 512 2`
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ciupload_fw $fwname1 $fw_file1
20362306a36Sopenharmony_ciupload_fw $fwname2 $fw_file2
20462306a36Sopenharmony_ciupload_fw $fwname3 $fw_file3
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_civerify_fw ${fwname1} ${fw_file1}
20762306a36Sopenharmony_civerify_fw ${fwname2} ${fw_file2}
20862306a36Sopenharmony_civerify_fw ${fwname3} ${fw_file3}
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ciecho -n "$fwname1" > "$DIR"/upload_unregister
21162306a36Sopenharmony_ciecho -n "$fwname2" > "$DIR"/upload_unregister
21262306a36Sopenharmony_ciecho -n "$fwname3" > "$DIR"/upload_unregister
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ciexit 0
215