fw_filesystem.sh 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. #!/bin/bash
  2. # SPDX-License-Identifier: GPL-2.0
  3. # This validates that the kernel will load firmware out of its list of
  4. # firmware locations on disk. Since the user helper does similar work,
  5. # we reset the custom load directory to a location the user helper doesn't
  6. # know so we can be sure we're not accidentally testing the user helper.
  7. set -e
  8. TEST_REQS_FW_SYSFS_FALLBACK="no"
  9. TEST_REQS_FW_SET_CUSTOM_PATH="yes"
  10. TEST_DIR=$(dirname $0)
  11. source $TEST_DIR/fw_lib.sh
  12. check_mods
  13. check_setup
  14. verify_reqs
  15. setup_tmp_file
  16. trap "test_finish" EXIT
  17. if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
  18. # Turn down the timeout so failures don't take so long.
  19. echo 1 >/sys/class/firmware/timeout
  20. fi
  21. if printf '\000' >"$DIR"/trigger_request 2> /dev/null; then
  22. echo "$0: empty filename should not succeed" >&2
  23. exit 1
  24. fi
  25. if [ ! -e "$DIR"/trigger_async_request ]; then
  26. echo "$0: empty filename: async trigger not present, ignoring test" >&2
  27. else
  28. if printf '\000' >"$DIR"/trigger_async_request 2> /dev/null; then
  29. echo "$0: empty filename should not succeed (async)" >&2
  30. exit 1
  31. fi
  32. fi
  33. # Request a firmware that doesn't exist, it should fail.
  34. if echo -n "nope-$NAME" >"$DIR"/trigger_request 2> /dev/null; then
  35. echo "$0: firmware shouldn't have loaded" >&2
  36. exit 1
  37. fi
  38. if diff -q "$FW" /dev/test_firmware >/dev/null ; then
  39. echo "$0: firmware was not expected to match" >&2
  40. exit 1
  41. else
  42. if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
  43. echo "$0: timeout works"
  44. fi
  45. fi
  46. # This should succeed via kernel load or will fail after 1 second after
  47. # being handed over to the user helper, which won't find the fw either.
  48. if ! echo -n "$NAME" >"$DIR"/trigger_request ; then
  49. echo "$0: could not trigger request" >&2
  50. exit 1
  51. fi
  52. # Verify the contents are what we expect.
  53. if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
  54. echo "$0: firmware was not loaded" >&2
  55. exit 1
  56. else
  57. echo "$0: filesystem loading works"
  58. fi
  59. # Try the asynchronous version too
  60. if [ ! -e "$DIR"/trigger_async_request ]; then
  61. echo "$0: firmware loading: async trigger not present, ignoring test" >&2
  62. else
  63. if ! echo -n "$NAME" >"$DIR"/trigger_async_request ; then
  64. echo "$0: could not trigger async request" >&2
  65. exit 1
  66. fi
  67. # Verify the contents are what we expect.
  68. if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
  69. echo "$0: firmware was not loaded (async)" >&2
  70. exit 1
  71. else
  72. echo "$0: async filesystem loading works"
  73. fi
  74. fi
  75. ### Batched requests tests
  76. test_config_present()
  77. {
  78. if [ ! -f $DIR/reset ]; then
  79. echo "Configuration triggers not present, ignoring test"
  80. exit 0
  81. fi
  82. }
  83. # Defaults :
  84. #
  85. # send_uevent: 1
  86. # sync_direct: 0
  87. # name: test-firmware.bin
  88. # num_requests: 4
  89. config_reset()
  90. {
  91. echo 1 > $DIR/reset
  92. }
  93. release_all_firmware()
  94. {
  95. echo 1 > $DIR/release_all_firmware
  96. }
  97. config_set_name()
  98. {
  99. echo -n $1 > $DIR/config_name
  100. }
  101. config_set_sync_direct()
  102. {
  103. echo 1 > $DIR/config_sync_direct
  104. }
  105. config_unset_sync_direct()
  106. {
  107. echo 0 > $DIR/config_sync_direct
  108. }
  109. config_set_uevent()
  110. {
  111. echo 1 > $DIR/config_send_uevent
  112. }
  113. config_unset_uevent()
  114. {
  115. echo 0 > $DIR/config_send_uevent
  116. }
  117. config_trigger_sync()
  118. {
  119. echo -n 1 > $DIR/trigger_batched_requests 2>/dev/null
  120. }
  121. config_trigger_async()
  122. {
  123. echo -n 1 > $DIR/trigger_batched_requests_async 2> /dev/null
  124. }
  125. config_set_read_fw_idx()
  126. {
  127. echo -n $1 > $DIR/config_read_fw_idx 2> /dev/null
  128. }
  129. read_firmwares()
  130. {
  131. for i in $(seq 0 3); do
  132. config_set_read_fw_idx $i
  133. # Verify the contents are what we expect.
  134. # -Z required for now -- check for yourself, md5sum
  135. # on $FW and DIR/read_firmware will yield the same. Even
  136. # cmp agrees, so something is off.
  137. if ! diff -q -Z "$FW" $DIR/read_firmware 2>/dev/null ; then
  138. echo "request #$i: firmware was not loaded" >&2
  139. exit 1
  140. fi
  141. done
  142. }
  143. read_firmwares_expect_nofile()
  144. {
  145. for i in $(seq 0 3); do
  146. config_set_read_fw_idx $i
  147. # Ensures contents differ
  148. if diff -q -Z "$FW" $DIR/read_firmware 2>/dev/null ; then
  149. echo "request $i: file was not expected to match" >&2
  150. exit 1
  151. fi
  152. done
  153. }
  154. test_batched_request_firmware_nofile()
  155. {
  156. echo -n "Batched request_firmware() nofile try #$1: "
  157. config_reset
  158. config_set_name nope-test-firmware.bin
  159. config_trigger_sync
  160. read_firmwares_expect_nofile
  161. release_all_firmware
  162. echo "OK"
  163. }
  164. test_batched_request_firmware_direct_nofile()
  165. {
  166. echo -n "Batched request_firmware_direct() nofile try #$1: "
  167. config_reset
  168. config_set_name nope-test-firmware.bin
  169. config_set_sync_direct
  170. config_trigger_sync
  171. release_all_firmware
  172. echo "OK"
  173. }
  174. test_request_firmware_nowait_uevent_nofile()
  175. {
  176. echo -n "Batched request_firmware_nowait(uevent=true) nofile try #$1: "
  177. config_reset
  178. config_set_name nope-test-firmware.bin
  179. config_trigger_async
  180. release_all_firmware
  181. echo "OK"
  182. }
  183. test_wait_and_cancel_custom_load()
  184. {
  185. if [ "$HAS_FW_LOADER_USER_HELPER" != "yes" ]; then
  186. return
  187. fi
  188. local timeout=10
  189. name=$1
  190. while [ ! -e "$DIR"/"$name"/loading ]; do
  191. sleep 0.1
  192. timeout=$(( $timeout - 1 ))
  193. if [ "$timeout" -eq 0 ]; then
  194. echo "firmware interface never appeared:" >&2
  195. echo "$DIR/$name/loading" >&2
  196. exit 1
  197. fi
  198. done
  199. echo -1 >"$DIR"/"$name"/loading
  200. }
  201. test_request_firmware_nowait_custom_nofile()
  202. {
  203. echo -n "Batched request_firmware_nowait(uevent=false) nofile try #$1: "
  204. config_reset
  205. config_unset_uevent
  206. RANDOM_FILE_PATH=$(setup_random_file_fake)
  207. RANDOM_FILE="$(basename $RANDOM_FILE_PATH)"
  208. config_set_name $RANDOM_FILE
  209. config_trigger_async &
  210. test_wait_and_cancel_custom_load $RANDOM_FILE
  211. wait
  212. release_all_firmware
  213. echo "OK"
  214. }
  215. test_batched_request_firmware()
  216. {
  217. echo -n "Batched request_firmware() try #$1: "
  218. config_reset
  219. config_trigger_sync
  220. read_firmwares
  221. release_all_firmware
  222. echo "OK"
  223. }
  224. test_batched_request_firmware_direct()
  225. {
  226. echo -n "Batched request_firmware_direct() try #$1: "
  227. config_reset
  228. config_set_sync_direct
  229. config_trigger_sync
  230. release_all_firmware
  231. echo "OK"
  232. }
  233. test_request_firmware_nowait_uevent()
  234. {
  235. echo -n "Batched request_firmware_nowait(uevent=true) try #$1: "
  236. config_reset
  237. config_trigger_async
  238. release_all_firmware
  239. echo "OK"
  240. }
  241. test_request_firmware_nowait_custom()
  242. {
  243. echo -n "Batched request_firmware_nowait(uevent=false) try #$1: "
  244. config_reset
  245. config_unset_uevent
  246. RANDOM_FILE_PATH=$(setup_random_file)
  247. RANDOM_FILE="$(basename $RANDOM_FILE_PATH)"
  248. config_set_name $RANDOM_FILE
  249. config_trigger_async
  250. release_all_firmware
  251. echo "OK"
  252. }
  253. # Only continue if batched request triggers are present on the
  254. # test-firmware driver
  255. test_config_present
  256. # test with the file present
  257. echo
  258. echo "Testing with the file present..."
  259. for i in $(seq 1 5); do
  260. test_batched_request_firmware $i
  261. done
  262. for i in $(seq 1 5); do
  263. test_batched_request_firmware_direct $i
  264. done
  265. for i in $(seq 1 5); do
  266. test_request_firmware_nowait_uevent $i
  267. done
  268. for i in $(seq 1 5); do
  269. test_request_firmware_nowait_custom $i
  270. done
  271. # Test for file not found, errors are expected, the failure would be
  272. # a hung task, which would require a hard reset.
  273. echo
  274. echo "Testing with the file missing..."
  275. for i in $(seq 1 5); do
  276. test_batched_request_firmware_nofile $i
  277. done
  278. for i in $(seq 1 5); do
  279. test_batched_request_firmware_direct_nofile $i
  280. done
  281. for i in $(seq 1 5); do
  282. test_request_firmware_nowait_uevent_nofile $i
  283. done
  284. for i in $(seq 1 5); do
  285. test_request_firmware_nowait_custom_nofile $i
  286. done
  287. exit 0