diff options
Diffstat (limited to 'tools/testing/selftests/firmware/fw_upload.sh')
-rwxr-xr-x | tools/testing/selftests/firmware/fw_upload.sh | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/tools/testing/selftests/firmware/fw_upload.sh b/tools/testing/selftests/firmware/fw_upload.sh new file mode 100755 index 000000000000..c7a6f06c9adb --- /dev/null +++ b/tools/testing/selftests/firmware/fw_upload.sh @@ -0,0 +1,214 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# This validates the user-initiated fw upload mechanism of the firmware +# loader. It verifies that one or more firmware devices can be created +# for a device driver. It also verifies the data transfer, the +# cancellation support, and the error flows. +set -e + +TEST_REQS_FW_UPLOAD="yes" +TEST_DIR=$(dirname $0) + +progress_states="preparing transferring programming" +errors="hw-error + timeout + device-busy + invalid-file-size + read-write-error + flash-wearout" +error_abort="user-abort" +fwname1=fw1 +fwname2=fw2 +fwname3=fw3 + +source $TEST_DIR/fw_lib.sh + +check_mods +check_setup +verify_reqs + +trap "upload_finish" EXIT + +upload_finish() { + local fwdevs="$fwname1 $fwname2 $fwname3" + + for name in $fwdevs; do + if [ -e "$DIR/$name" ]; then + echo -n "$name" > "$DIR"/upload_unregister + fi + done +} + +upload_fw() { + local name="$1" + local file="$2" + + echo 1 > "$DIR"/"$name"/loading + cat "$file" > "$DIR"/"$name"/data + echo 0 > "$DIR"/"$name"/loading +} + +verify_fw() { + local name="$1" + local file="$2" + + echo -n "$name" > "$DIR"/config_upload_name + if ! cmp "$file" "$DIR"/upload_read > /dev/null 2>&1; then + echo "$0: firmware compare for $name did not match" >&2 + exit 1 + fi + + echo "$0: firmware upload for $name works" >&2 + return 0 +} + +inject_error() { + local name="$1" + local status="$2" + local error="$3" + + echo 1 > "$DIR"/"$name"/loading + echo -n "inject":"$status":"$error" > "$DIR"/"$name"/data + echo 0 > "$DIR"/"$name"/loading +} + +await_status() { + local name="$1" + local expected="$2" + local status + local i + + let i=0 + while [ $i -lt 50 ]; do + status=$(cat "$DIR"/"$name"/status) + if [ "$status" = "$expected" ]; then + return 0; + fi + sleep 1e-03 + let i=$i+1 + done + + echo "$0: Invalid status: Expected $expected, Actual $status" >&2 + return 1; +} + +await_idle() { + local name="$1" + + await_status "$name" "idle" + return $? +} + +expect_error() { + local name="$1" + local expected="$2" + local error=$(cat "$DIR"/"$name"/error) + + if [ "$error" != "$expected" ]; then + echo "Invalid error: Expected $expected, Actual $error" >&2 + return 1 + fi + + return 0 +} + +random_firmware() { + local bs="$1" + local count="$2" + local file=$(mktemp -p /tmp uploadfwXXX.bin) + + dd if=/dev/urandom of="$file" bs="$bs" count="$count" > /dev/null 2>&1 + echo "$file" +} + +test_upload_cancel() { + local name="$1" + local status + + for status in $progress_states; do + inject_error $name $status $error_abort + if ! await_status $name $status; then + exit 1 + fi + + echo 1 > "$DIR"/"$name"/cancel + + if ! await_idle $name; then + exit 1 + fi + + if ! expect_error $name "$status":"$error_abort"; then + exit 1 + fi + done + + echo "$0: firmware upload cancellation works" + return 0 +} + +test_error_handling() { + local name=$1 + local status + local error + + for status in $progress_states; do + for error in $errors; do + inject_error $name $status $error + + if ! await_idle $name; then + exit 1 + fi + + if ! expect_error $name "$status":"$error"; then + exit 1 + fi + + done + done + echo "$0: firmware upload error handling works" +} + +test_fw_too_big() { + local name=$1 + local fw_too_big=`random_firmware 512 5` + local expected="preparing:invalid-file-size" + + upload_fw $name $fw_too_big + rm -f $fw_too_big + + if ! await_idle $name; then + exit 1 + fi + + if ! expect_error $name $expected; then + exit 1 + fi + + echo "$0: oversized firmware error handling works" +} + +echo -n "$fwname1" > "$DIR"/upload_register +echo -n "$fwname2" > "$DIR"/upload_register +echo -n "$fwname3" > "$DIR"/upload_register + +test_upload_cancel $fwname1 +test_error_handling $fwname1 +test_fw_too_big $fwname1 + +fw_file1=`random_firmware 512 4` +fw_file2=`random_firmware 512 3` +fw_file3=`random_firmware 512 2` + +upload_fw $fwname1 $fw_file1 +upload_fw $fwname2 $fw_file2 +upload_fw $fwname3 $fw_file3 + +verify_fw ${fwname1} ${fw_file1} +verify_fw ${fwname2} ${fw_file2} +verify_fw ${fwname3} ${fw_file3} + +echo -n "$fwname1" > "$DIR"/upload_unregister +echo -n "$fwname2" > "$DIR"/upload_unregister +echo -n "$fwname3" > "$DIR"/upload_unregister + +exit 0 |