fw_upload.sh 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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.
  7. set -e
  8. TEST_REQS_FW_UPLOAD="yes"
  9. TEST_DIR=$(dirname $0)
  10. progress_states="preparing transferring programming"
  11. errors="hw-error
  12. timeout
  13. device-busy
  14. invalid-file-size
  15. read-write-error
  16. flash-wearout"
  17. error_abort="user-abort"
  18. fwname1=fw1
  19. fwname2=fw2
  20. fwname3=fw3
  21. source $TEST_DIR/fw_lib.sh
  22. check_mods
  23. check_setup
  24. verify_reqs
  25. trap "upload_finish" EXIT
  26. upload_finish() {
  27. local fwdevs="$fwname1 $fwname2 $fwname3"
  28. for name in $fwdevs; do
  29. if [ -e "$DIR/$name" ]; then
  30. echo -n "$name" > "$DIR"/upload_unregister
  31. fi
  32. done
  33. }
  34. upload_fw() {
  35. local name="$1"
  36. local file="$2"
  37. echo 1 > "$DIR"/"$name"/loading
  38. cat "$file" > "$DIR"/"$name"/data
  39. echo 0 > "$DIR"/"$name"/loading
  40. }
  41. verify_fw() {
  42. local name="$1"
  43. local file="$2"
  44. echo -n "$name" > "$DIR"/config_upload_name
  45. if ! cmp "$file" "$DIR"/upload_read > /dev/null 2>&1; then
  46. echo "$0: firmware compare for $name did not match" >&2
  47. exit 1
  48. fi
  49. echo "$0: firmware upload for $name works" >&2
  50. return 0
  51. }
  52. inject_error() {
  53. local name="$1"
  54. local status="$2"
  55. local error="$3"
  56. echo 1 > "$DIR"/"$name"/loading
  57. echo -n "inject":"$status":"$error" > "$DIR"/"$name"/data
  58. echo 0 > "$DIR"/"$name"/loading
  59. }
  60. await_status() {
  61. local name="$1"
  62. local expected="$2"
  63. local status
  64. local i
  65. let i=0
  66. while [ $i -lt 50 ]; do
  67. status=$(cat "$DIR"/"$name"/status)
  68. if [ "$status" = "$expected" ]; then
  69. return 0;
  70. fi
  71. sleep 1e-03
  72. let i=$i+1
  73. done
  74. echo "$0: Invalid status: Expected $expected, Actual $status" >&2
  75. return 1;
  76. }
  77. await_idle() {
  78. local name="$1"
  79. await_status "$name" "idle"
  80. return $?
  81. }
  82. expect_error() {
  83. local name="$1"
  84. local expected="$2"
  85. local error=$(cat "$DIR"/"$name"/error)
  86. if [ "$error" != "$expected" ]; then
  87. echo "Invalid error: Expected $expected, Actual $error" >&2
  88. return 1
  89. fi
  90. return 0
  91. }
  92. random_firmware() {
  93. local bs="$1"
  94. local count="$2"
  95. local file=$(mktemp -p /tmp uploadfwXXX.bin)
  96. dd if=/dev/urandom of="$file" bs="$bs" count="$count" > /dev/null 2>&1
  97. echo "$file"
  98. }
  99. test_upload_cancel() {
  100. local name="$1"
  101. local status
  102. for status in $progress_states; do
  103. inject_error $name $status $error_abort
  104. if ! await_status $name $status; then
  105. exit 1
  106. fi
  107. echo 1 > "$DIR"/"$name"/cancel
  108. if ! await_idle $name; then
  109. exit 1
  110. fi
  111. if ! expect_error $name "$status":"$error_abort"; then
  112. exit 1
  113. fi
  114. done
  115. echo "$0: firmware upload cancellation works"
  116. return 0
  117. }
  118. test_error_handling() {
  119. local name=$1
  120. local status
  121. local error
  122. for status in $progress_states; do
  123. for error in $errors; do
  124. inject_error $name $status $error
  125. if ! await_idle $name; then
  126. exit 1
  127. fi
  128. if ! expect_error $name "$status":"$error"; then
  129. exit 1
  130. fi
  131. done
  132. done
  133. echo "$0: firmware upload error handling works"
  134. }
  135. test_fw_too_big() {
  136. local name=$1
  137. local fw_too_big=`random_firmware 512 5`
  138. local expected="preparing:invalid-file-size"
  139. upload_fw $name $fw_too_big
  140. rm -f $fw_too_big
  141. if ! await_idle $name; then
  142. exit 1
  143. fi
  144. if ! expect_error $name $expected; then
  145. exit 1
  146. fi
  147. echo "$0: oversized firmware error handling works"
  148. }
  149. echo -n "$fwname1" > "$DIR"/upload_register
  150. echo -n "$fwname2" > "$DIR"/upload_register
  151. echo -n "$fwname3" > "$DIR"/upload_register
  152. test_upload_cancel $fwname1
  153. test_error_handling $fwname1
  154. test_fw_too_big $fwname1
  155. fw_file1=`random_firmware 512 4`
  156. fw_file2=`random_firmware 512 3`
  157. fw_file3=`random_firmware 512 2`
  158. upload_fw $fwname1 $fw_file1
  159. upload_fw $fwname2 $fw_file2
  160. upload_fw $fwname3 $fw_file3
  161. verify_fw ${fwname1} ${fw_file1}
  162. verify_fw ${fwname2} ${fw_file2}
  163. verify_fw ${fwname3} ${fw_file3}
  164. echo -n "$fwname1" > "$DIR"/upload_unregister
  165. echo -n "$fwname2" > "$DIR"/upload_unregister
  166. echo -n "$fwname3" > "$DIR"/upload_unregister
  167. exit 0