]> git.baikalelectronics.ru Git - kernel.git/commitdiff
selftests: firmware: Add firmware upload selftests
authorRuss Weight <russell.h.weight@intel.com>
Tue, 26 Apr 2022 16:35:32 +0000 (09:35 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 29 Apr 2022 14:49:36 +0000 (16:49 +0200)
Add selftests to verify the firmware upload mechanism. These test
include simple firmware uploads as well as upload cancellation and
error injection. The test creates three firmware devices and verifies
that they all work correctly and independently.

Tested-by: Matthew Gerlach <matthew.gerlach@linux.intel.com>
Reviewed-by: Luis Chamberlain <mcgrof@kernel.org>
Reviewed-by: Tianfei zhang <tianfei.zhang@intel.com>
Signed-off-by: Russ Weight <russell.h.weight@intel.com>
Link: https://lore.kernel.org/r/20220426163532.114961-1-russell.h.weight@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
tools/testing/selftests/firmware/Makefile
tools/testing/selftests/firmware/config
tools/testing/selftests/firmware/fw_lib.sh
tools/testing/selftests/firmware/fw_run_tests.sh
tools/testing/selftests/firmware/fw_upload.sh [new file with mode: 0755]

index 40211cd8f0e6c8fd58f8eb2ff2643274a895c93f..7992969deaa2737ff2a033ffe60136b84ea2f3f0 100644 (file)
@@ -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
index bf634dda07201fe7108f16496834543223164204..6e402519b1173738fc7fcd20cdc43f637059ddd1 100644 (file)
@@ -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
index 3fa8282b053bac1308b1044f1081df0a9b145bf6..7bffd67800bf483b8376a076c6431e839367bf69 100755 (executable)
@@ -64,6 +64,7 @@ check_setup()
        HAS_FW_LOADER_USER_HELPER_FALLBACK="$(kconfig_has CONFIG_FW_LOADER_USER_HELPER_FALLBACK=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"
 
@@ -119,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()
index 777377078d5e3777b9a8084b78534a8f8ba4a9bc..f6d95a2d512497df12a3c0429c34ed5f8e2f3d43 100755 (executable)
@@ -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 (executable)
index 0000000..c7a6f06
--- /dev/null
@@ -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