1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3# This validates the user-initiated fw upload mechanism of the firmware 4# loader. It verifies that one or more firmware devices can be created 5# for a device driver. It also verifies the data transfer, the 6# cancellation support, and the error flows. 7set -e 8 9TEST_REQS_FW_UPLOAD="yes" 10TEST_DIR=$(dirname $0) 11 12progress_states="preparing transferring programming" 13errors="hw-error 14 timeout 15 device-busy 16 invalid-file-size 17 read-write-error 18 flash-wearout" 19error_abort="user-abort" 20fwname1=fw1 21fwname2=fw2 22fwname3=fw3 23 24source $TEST_DIR/fw_lib.sh 25 26check_mods 27check_setup 28verify_reqs 29 30trap "upload_finish" EXIT 31 32upload_finish() { 33 local fwdevs="$fwname1 $fwname2 $fwname3" 34 35 for name in $fwdevs; do 36 if [ -e "$DIR/$name" ]; then 37 echo -n "$name" > "$DIR"/upload_unregister 38 fi 39 done 40} 41 42upload_fw() { 43 local name="$1" 44 local file="$2" 45 46 echo 1 > "$DIR"/"$name"/loading 47 cat "$file" > "$DIR"/"$name"/data 48 echo 0 > "$DIR"/"$name"/loading 49} 50 51verify_fw() { 52 local name="$1" 53 local file="$2" 54 55 echo -n "$name" > "$DIR"/config_upload_name 56 if ! cmp "$file" "$DIR"/upload_read > /dev/null 2>&1; then 57 echo "$0: firmware compare for $name did not match" >&2 58 exit 1 59 fi 60 61 echo "$0: firmware upload for $name works" >&2 62 return 0 63} 64 65inject_error() { 66 local name="$1" 67 local status="$2" 68 local error="$3" 69 70 echo 1 > "$DIR"/"$name"/loading 71 echo -n "inject":"$status":"$error" > "$DIR"/"$name"/data 72 echo 0 > "$DIR"/"$name"/loading 73} 74 75await_status() { 76 local name="$1" 77 local expected="$2" 78 local status 79 local i 80 81 let i=0 82 while [ $i -lt 50 ]; do 83 status=$(cat "$DIR"/"$name"/status) 84 if [ "$status" = "$expected" ]; then 85 return 0; 86 fi 87 sleep 1e-03 88 let i=$i+1 89 done 90 91 echo "$0: Invalid status: Expected $expected, Actual $status" >&2 92 return 1; 93} 94 95await_idle() { 96 local name="$1" 97 98 await_status "$name" "idle" 99 return $? 100} 101 102expect_error() { 103 local name="$1" 104 local expected="$2" 105 local error=$(cat "$DIR"/"$name"/error) 106 107 if [ "$error" != "$expected" ]; then 108 echo "Invalid error: Expected $expected, Actual $error" >&2 109 return 1 110 fi 111 112 return 0 113} 114 115random_firmware() { 116 local bs="$1" 117 local count="$2" 118 local file=$(mktemp -p /tmp uploadfwXXX.bin) 119 120 dd if=/dev/urandom of="$file" bs="$bs" count="$count" > /dev/null 2>&1 121 echo "$file" 122} 123 124test_upload_cancel() { 125 local name="$1" 126 local status 127 128 for status in $progress_states; do 129 inject_error $name $status $error_abort 130 if ! await_status $name $status; then 131 exit 1 132 fi 133 134 echo 1 > "$DIR"/"$name"/cancel 135 136 if ! await_idle $name; then 137 exit 1 138 fi 139 140 if ! expect_error $name "$status":"$error_abort"; then 141 exit 1 142 fi 143 done 144 145 echo "$0: firmware upload cancellation works" 146 return 0 147} 148 149test_error_handling() { 150 local name=$1 151 local status 152 local error 153 154 for status in $progress_states; do 155 for error in $errors; do 156 inject_error $name $status $error 157 158 if ! await_idle $name; then 159 exit 1 160 fi 161 162 if ! expect_error $name "$status":"$error"; then 163 exit 1 164 fi 165 166 done 167 done 168 echo "$0: firmware upload error handling works" 169} 170 171test_fw_too_big() { 172 local name=$1 173 local fw_too_big=`random_firmware 512 5` 174 local expected="preparing:invalid-file-size" 175 176 upload_fw $name $fw_too_big 177 rm -f $fw_too_big 178 179 if ! await_idle $name; then 180 exit 1 181 fi 182 183 if ! expect_error $name $expected; then 184 exit 1 185 fi 186 187 echo "$0: oversized firmware error handling works" 188} 189 190echo -n "$fwname1" > "$DIR"/upload_register 191echo -n "$fwname2" > "$DIR"/upload_register 192echo -n "$fwname3" > "$DIR"/upload_register 193 194test_upload_cancel $fwname1 195test_error_handling $fwname1 196test_fw_too_big $fwname1 197 198fw_file1=`random_firmware 512 4` 199fw_file2=`random_firmware 512 3` 200fw_file3=`random_firmware 512 2` 201 202upload_fw $fwname1 $fw_file1 203upload_fw $fwname2 $fw_file2 204upload_fw $fwname3 $fw_file3 205 206verify_fw ${fwname1} ${fw_file1} 207verify_fw ${fwname2} ${fw_file2} 208verify_fw ${fwname3} ${fw_file3} 209 210echo -n "$fwname1" > "$DIR"/upload_unregister 211echo -n "$fwname2" > "$DIR"/upload_unregister 212echo -n "$fwname3" > "$DIR"/upload_unregister 213 214exit 0 215