diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/testing/selftests/firmware/Makefile | 2 | ||||
-rw-r--r-- | tools/testing/selftests/firmware/config | 1 | ||||
-rwxr-xr-x | tools/testing/selftests/firmware/fw_filesystem.sh | 170 | ||||
-rwxr-xr-x | tools/testing/selftests/firmware/fw_lib.sh | 19 | ||||
-rwxr-xr-x | tools/testing/selftests/firmware/fw_run_tests.sh | 4 | ||||
-rwxr-xr-x | tools/testing/selftests/firmware/fw_upload.sh | 214 |
6 files changed, 318 insertions, 92 deletions
diff --git a/tools/testing/selftests/firmware/Makefile b/tools/testing/selftests/firmware/Makefile index 40211cd8f0e6..7992969deaa2 100644 --- a/tools/testing/selftests/firmware/Makefile +++ b/tools/testing/selftests/firmware/Makefile @@ -4,7 +4,7 @@ CFLAGS = -Wall \ -O2 TEST_PROGS := fw_run_tests.sh -TEST_FILES := fw_fallback.sh fw_filesystem.sh fw_lib.sh +TEST_FILES := fw_fallback.sh fw_filesystem.sh fw_upload.sh fw_lib.sh TEST_GEN_FILES := fw_namespace include ../lib.mk diff --git a/tools/testing/selftests/firmware/config b/tools/testing/selftests/firmware/config index bf634dda0720..6e402519b117 100644 --- a/tools/testing/selftests/firmware/config +++ b/tools/testing/selftests/firmware/config @@ -3,3 +3,4 @@ CONFIG_FW_LOADER=y CONFIG_FW_LOADER_USER_HELPER=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y +CONFIG_FW_UPLOAD=y diff --git a/tools/testing/selftests/firmware/fw_filesystem.sh b/tools/testing/selftests/firmware/fw_filesystem.sh index c2a2a100114b..1a99aea0549e 100755 --- a/tools/testing/selftests/firmware/fw_filesystem.sh +++ b/tools/testing/selftests/firmware/fw_filesystem.sh @@ -11,6 +11,9 @@ TEST_REQS_FW_SET_CUSTOM_PATH="yes" TEST_DIR=$(dirname $0) source $TEST_DIR/fw_lib.sh +RUN_XZ="xz -C crc32 --lzma2=dict=2MiB" +RUN_ZSTD="zstd -q" + check_mods check_setup verify_reqs @@ -211,7 +214,7 @@ read_firmwares() else fwfile="$FW" fi - if [ "$1" = "xzonly" ]; then + if [ "$1" = "componly" ]; then fwfile="${fwfile}-orig" fi for i in $(seq 0 3); do @@ -235,7 +238,7 @@ read_partial_firmwares() fwfile="${FW}" fi - if [ "$1" = "xzonly" ]; then + if [ "$1" = "componly" ]; then fwfile="${fwfile}-orig" fi @@ -409,10 +412,8 @@ test_request_firmware_nowait_custom() config_unset_uevent RANDOM_FILE_PATH=$(setup_random_file) RANDOM_FILE="$(basename $RANDOM_FILE_PATH)" - if [ "$2" = "both" ]; then - xz -9 -C crc32 -k $RANDOM_FILE_PATH - elif [ "$2" = "xzonly" ]; then - xz -9 -C crc32 $RANDOM_FILE_PATH + if [ -n "$2" -a "$2" != "normal" ]; then + compress_"$2"_"$COMPRESS_FORMAT" $RANDOM_FILE_PATH fi config_set_name $RANDOM_FILE config_trigger_async @@ -435,6 +436,32 @@ test_request_partial_firmware_into_buf() echo "OK" } +do_tests () +{ + mode="$1" + suffix="$2" + + for i in $(seq 1 5); do + test_batched_request_firmware$suffix $i $mode + done + + for i in $(seq 1 5); do + test_batched_request_firmware_into_buf$suffix $i $mode + done + + for i in $(seq 1 5); do + test_batched_request_firmware_direct$suffix $i $mode + done + + for i in $(seq 1 5); do + test_request_firmware_nowait_uevent$suffix $i $mode + done + + for i in $(seq 1 5); do + test_request_firmware_nowait_custom$suffix $i $mode + done +} + # Only continue if batched request triggers are present on the # test-firmware driver test_config_present @@ -442,25 +469,7 @@ test_config_present # test with the file present echo echo "Testing with the file present..." -for i in $(seq 1 5); do - test_batched_request_firmware $i normal -done - -for i in $(seq 1 5); do - test_batched_request_firmware_into_buf $i normal -done - -for i in $(seq 1 5); do - test_batched_request_firmware_direct $i normal -done - -for i in $(seq 1 5); do - test_request_firmware_nowait_uevent $i normal -done - -for i in $(seq 1 5); do - test_request_firmware_nowait_custom $i normal -done +do_tests normal # Partial loads cannot use fallback, so do not repeat tests. test_request_partial_firmware_into_buf 0 10 @@ -472,25 +481,7 @@ test_request_partial_firmware_into_buf 2 10 # 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 - -for i in $(seq 1 5); do - test_batched_request_firmware_into_buf_nofile $i -done - -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 +do_tests nofile _nofile # Partial loads cannot use fallback, so do not repeat tests. test_request_partial_firmware_into_buf_nofile 0 10 @@ -498,55 +489,58 @@ test_request_partial_firmware_into_buf_nofile 0 5 test_request_partial_firmware_into_buf_nofile 1 6 test_request_partial_firmware_into_buf_nofile 2 10 -test "$HAS_FW_LOADER_COMPRESS" != "yes" && exit 0 +test_request_firmware_compressed () +{ + export COMPRESS_FORMAT="$1" -# 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 + # test with both files present + compress_both_"$COMPRESS_FORMAT" $FW + compress_both_"$COMPRESS_FORMAT" $FW_INTO_BUF -for i in $(seq 1 5); do - test_batched_request_firmware_into_buf $i both -done + config_set_name $NAME + echo + echo "Testing with both plain and $COMPRESS_FORMAT files present..." + do_tests both -for i in $(seq 1 5); do - test_batched_request_firmware_direct $i both -done + # test with only compressed file present + mv "$FW" "${FW}-orig" + mv "$FW_INTO_BUF" "${FW_INTO_BUF}-orig" -for i in $(seq 1 5); do - test_request_firmware_nowait_uevent $i both -done + config_set_name $NAME + echo + echo "Testing with only $COMPRESS_FORMAT file present..." + do_tests componly -for i in $(seq 1 5); do - test_request_firmware_nowait_custom $i both -done + mv "${FW}-orig" "$FW" + mv "${FW_INTO_BUF}-orig" "$FW_INTO_BUF" +} -# 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 - -for i in $(seq 1 5); do - test_batched_request_firmware_into_buf $i xzonly -done - -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 +compress_both_XZ () +{ + $RUN_XZ -k "$@" +} + +compress_componly_XZ () +{ + $RUN_XZ "$@" +} + +compress_both_ZSTD () +{ + $RUN_ZSTD -k "$@" +} + +compress_componly_ZSTD () +{ + $RUN_ZSTD --rm "$@" +} + +if test "$HAS_FW_LOADER_COMPRESS_XZ" = "yes"; then + test_request_firmware_compressed XZ +fi + +if test "$HAS_FW_LOADER_COMPRESS_ZSTD" = "yes"; then + test_request_firmware_compressed ZSTD +fi exit 0 diff --git a/tools/testing/selftests/firmware/fw_lib.sh b/tools/testing/selftests/firmware/fw_lib.sh index 5b8c0fedee76..7bffd67800bf 100755 --- a/tools/testing/selftests/firmware/fw_lib.sh +++ b/tools/testing/selftests/firmware/fw_lib.sh @@ -62,7 +62,9 @@ check_setup() { HAS_FW_LOADER_USER_HELPER="$(kconfig_has CONFIG_FW_LOADER_USER_HELPER=y)" HAS_FW_LOADER_USER_HELPER_FALLBACK="$(kconfig_has CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y)" - HAS_FW_LOADER_COMPRESS="$(kconfig_has CONFIG_FW_LOADER_COMPRESS=y)" + HAS_FW_LOADER_COMPRESS_XZ="$(kconfig_has CONFIG_FW_LOADER_COMPRESS_XZ=y)" + HAS_FW_LOADER_COMPRESS_ZSTD="$(kconfig_has CONFIG_FW_LOADER_COMPRESS_ZSTD=y)" + HAS_FW_UPLOAD="$(kconfig_has CONFIG_FW_UPLOAD=y)" PROC_FW_IGNORE_SYSFS_FALLBACK="0" PROC_FW_FORCE_SYSFS_FALLBACK="0" @@ -98,9 +100,14 @@ check_setup() OLD_FWPATH="$(cat /sys/module/firmware_class/parameters/path)" - if [ "$HAS_FW_LOADER_COMPRESS" = "yes" ]; then + if [ "$HAS_FW_LOADER_COMPRESS_XZ" = "yes" ]; then if ! which xz 2> /dev/null > /dev/null; then - HAS_FW_LOADER_COMPRESS="" + HAS_FW_LOADER_COMPRESS_XZ="" + fi + fi + if [ "$HAS_FW_LOADER_COMPRESS_ZSTD" = "yes" ]; then + if ! which zstd 2> /dev/null > /dev/null; then + HAS_FW_LOADER_COMPRESS_ZSTD="" fi fi } @@ -113,6 +120,12 @@ verify_reqs() exit 0 fi fi + if [ "$TEST_REQS_FW_UPLOAD" = "yes" ]; then + if [ ! "$HAS_FW_UPLOAD" = "yes" ]; then + echo "firmware upload disabled so ignoring test" + exit 0 + fi + fi } setup_tmp_file() diff --git a/tools/testing/selftests/firmware/fw_run_tests.sh b/tools/testing/selftests/firmware/fw_run_tests.sh index 777377078d5e..f6d95a2d5124 100755 --- a/tools/testing/selftests/firmware/fw_run_tests.sh +++ b/tools/testing/selftests/firmware/fw_run_tests.sh @@ -22,6 +22,10 @@ run_tests() proc_set_force_sysfs_fallback $1 proc_set_ignore_sysfs_fallback $2 $TEST_DIR/fw_fallback.sh + + proc_set_force_sysfs_fallback $1 + proc_set_ignore_sysfs_fallback $2 + $TEST_DIR/fw_upload.sh } run_test_config_0001() 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 |