Path: blob/master/tools/testing/selftests/firmware/fw_filesystem.sh
26285 views
#!/bin/bash1# SPDX-License-Identifier: GPL-2.02# This validates that the kernel will load firmware out of its list of3# firmware locations on disk. Since the user helper does similar work,4# we reset the custom load directory to a location the user helper doesn't5# know so we can be sure we're not accidentally testing the user helper.6set -e78TEST_REQS_FW_SYSFS_FALLBACK="no"9TEST_REQS_FW_SET_CUSTOM_PATH="yes"10TEST_DIR=$(dirname $0)11source $TEST_DIR/fw_lib.sh1213RUN_XZ="xz -C crc32 --lzma2=dict=2MiB"14RUN_ZSTD="zstd -q"1516check_mods17check_setup18verify_reqs19setup_tmp_file2021trap "test_finish" EXIT2223if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then24# Turn down the timeout so failures don't take so long.25echo 1 >/sys/class/firmware/timeout26fi2728if printf '\000' >"$DIR"/trigger_request 2> /dev/null; then29echo "$0: empty filename should not succeed" >&230exit 131fi3233if [ ! -e "$DIR"/trigger_async_request ]; then34echo "$0: empty filename: async trigger not present, ignoring test" >&235exit $ksft_skip36else37if printf '\000' >"$DIR"/trigger_async_request 2> /dev/null; then38echo "$0: empty filename should not succeed (async)" >&239exit 140fi41fi4243# Request a firmware that doesn't exist, it should fail.44if echo -n "nope-$NAME" >"$DIR"/trigger_request 2> /dev/null; then45echo "$0: firmware shouldn't have loaded" >&246exit 147fi48if diff -q "$FW" /dev/test_firmware >/dev/null ; then49echo "$0: firmware was not expected to match" >&250exit 151else52if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then53echo "$0: timeout works"54fi55fi5657# This should succeed via kernel load or will fail after 1 second after58# being handed over to the user helper, which won't find the fw either.59if ! echo -n "$NAME" >"$DIR"/trigger_request ; then60echo "$0: could not trigger request" >&261exit 162fi6364# Verify the contents are what we expect.65if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then66echo "$0: firmware was not loaded" >&267exit 168else69echo "$0: filesystem loading works"70fi7172# Try the asynchronous version too73if [ ! -e "$DIR"/trigger_async_request ]; then74echo "$0: firmware loading: async trigger not present, ignoring test" >&275exit $ksft_skip76else77if ! echo -n "$NAME" >"$DIR"/trigger_async_request ; then78echo "$0: could not trigger async request" >&279exit 180fi8182# Verify the contents are what we expect.83if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then84echo "$0: firmware was not loaded (async)" >&285exit 186else87echo "$0: async filesystem loading works"88fi89fi9091# Try platform (EFI embedded fw) loading too92if [ ! -e "$DIR"/trigger_request_platform ]; then93echo "$0: firmware loading: platform trigger not present, ignoring test" >&294else95if printf '\000' >"$DIR"/trigger_request_platform 2> /dev/null; then96echo "$0: empty filename should not succeed (platform)" >&297exit 198fi99100# Note we echo a non-existing name, since files on the file-system101# are preferred over firmware embedded inside the platform's firmware102# The test adds a fake entry with the requested name to the platform's103# fw list, so the name does not matter as long as it does not exist104if ! echo -n "nope-$NAME" >"$DIR"/trigger_request_platform ; then105echo "$0: could not trigger request platform" >&2106exit 1107fi108109# The test verifies itself that the loaded firmware contents matches110# the contents for the fake platform fw entry it added.111echo "$0: platform loading works"112fi113114### Batched requests tests115test_config_present()116{117if [ ! -f $DIR/reset ]; then118echo "Configuration triggers not present, ignoring test"119exit $ksft_skip120fi121}122123# Defaults :124#125# send_uevent: 1126# sync_direct: 0127# name: test-firmware.bin128# num_requests: 4129config_reset()130{131echo 1 > $DIR/reset132}133134release_all_firmware()135{136echo 1 > $DIR/release_all_firmware137}138139config_set_name()140{141echo -n $1 > $DIR/config_name142}143144config_set_into_buf()145{146echo 1 > $DIR/config_into_buf147}148149config_unset_into_buf()150{151echo 0 > $DIR/config_into_buf152}153154config_set_buf_size()155{156echo $1 > $DIR/config_buf_size157}158159config_set_file_offset()160{161echo $1 > $DIR/config_file_offset162}163164config_set_partial()165{166echo 1 > $DIR/config_partial167}168169config_unset_partial()170{171echo 0 > $DIR/config_partial172}173174config_set_sync_direct()175{176echo 1 > $DIR/config_sync_direct177}178179config_unset_sync_direct()180{181echo 0 > $DIR/config_sync_direct182}183184config_set_uevent()185{186echo 1 > $DIR/config_send_uevent187}188189config_unset_uevent()190{191echo 0 > $DIR/config_send_uevent192}193194config_trigger_sync()195{196echo -n 1 > $DIR/trigger_batched_requests 2>/dev/null197}198199config_trigger_async()200{201echo -n 1 > $DIR/trigger_batched_requests_async 2> /dev/null202}203204config_set_read_fw_idx()205{206echo -n $1 > $DIR/config_read_fw_idx 2> /dev/null207}208209read_firmwares()210{211if [ "$(cat $DIR/config_into_buf)" == "1" ]; then212fwfile="$FW_INTO_BUF"213else214fwfile="$FW"215fi216if [ "$1" = "componly" ]; then217fwfile="${fwfile}-orig"218fi219for i in $(seq 0 3); do220config_set_read_fw_idx $i221# Verify the contents are what we expect.222# -Z required for now -- check for yourself, md5sum223# on $FW and DIR/read_firmware will yield the same. Even224# cmp agrees, so something is off.225if ! diff -q -Z "$fwfile" $DIR/read_firmware 2>/dev/null ; then226echo "request #$i: firmware was not loaded" >&2227exit 1228fi229done230}231232read_partial_firmwares()233{234if [ "$(cat $DIR/config_into_buf)" == "1" ]; then235fwfile="${FW_INTO_BUF}"236else237fwfile="${FW}"238fi239240if [ "$1" = "componly" ]; then241fwfile="${fwfile}-orig"242fi243244# Strip fwfile down to match partial offset and length245partial_data="$(cat $fwfile)"246partial_data="${partial_data:$2:$3}"247248for i in $(seq 0 3); do249config_set_read_fw_idx $i250251read_firmware="$(cat $DIR/read_firmware)"252253# Verify the contents are what we expect.254if [ $read_firmware != $partial_data ]; then255echo "request #$i: partial firmware was not loaded" >&2256exit 1257fi258done259}260261read_firmwares_expect_nofile()262{263for i in $(seq 0 3); do264config_set_read_fw_idx $i265# Ensures contents differ266if diff -q -Z "$FW" $DIR/read_firmware 2>/dev/null ; then267echo "request $i: file was not expected to match" >&2268exit 1269fi270done271}272273test_batched_request_firmware_nofile()274{275echo -n "Batched request_firmware() nofile try #$1: "276config_reset277config_set_name nope-test-firmware.bin278config_trigger_sync279read_firmwares_expect_nofile280release_all_firmware281echo "OK"282}283284test_batched_request_firmware_into_buf_nofile()285{286echo -n "Batched request_firmware_into_buf() nofile try #$1: "287config_reset288config_set_name nope-test-firmware.bin289config_set_into_buf290config_trigger_sync291read_firmwares_expect_nofile292release_all_firmware293echo "OK"294}295296test_request_partial_firmware_into_buf_nofile()297{298echo -n "Test request_partial_firmware_into_buf() off=$1 size=$2 nofile: "299config_reset300config_set_name nope-test-firmware.bin301config_set_into_buf302config_set_partial303config_set_buf_size $2304config_set_file_offset $1305config_trigger_sync306read_firmwares_expect_nofile307release_all_firmware308echo "OK"309}310311test_batched_request_firmware_direct_nofile()312{313echo -n "Batched request_firmware_direct() nofile try #$1: "314config_reset315config_set_name nope-test-firmware.bin316config_set_sync_direct317config_trigger_sync318release_all_firmware319echo "OK"320}321322test_request_firmware_nowait_uevent_nofile()323{324echo -n "Batched request_firmware_nowait(uevent=true) nofile try #$1: "325config_reset326config_set_name nope-test-firmware.bin327config_trigger_async328release_all_firmware329echo "OK"330}331332test_wait_and_cancel_custom_load()333{334if [ "$HAS_FW_LOADER_USER_HELPER" != "yes" ]; then335return336fi337local timeout=10338name=$1339while [ ! -e "$DIR"/"$name"/loading ]; do340sleep 0.1341timeout=$(( $timeout - 1 ))342if [ "$timeout" -eq 0 ]; then343echo "firmware interface never appeared:" >&2344echo "$DIR/$name/loading" >&2345exit 1346fi347done348echo -1 >"$DIR"/"$name"/loading349}350351test_request_firmware_nowait_custom_nofile()352{353echo -n "Batched request_firmware_nowait(uevent=false) nofile try #$1: "354config_reset355config_unset_uevent356RANDOM_FILE_PATH=$(setup_random_file_fake)357RANDOM_FILE="$(basename $RANDOM_FILE_PATH)"358config_set_name $RANDOM_FILE359config_trigger_async &360test_wait_and_cancel_custom_load $RANDOM_FILE361wait362release_all_firmware363echo "OK"364}365366test_batched_request_firmware()367{368echo -n "Batched request_firmware() $2 try #$1: "369config_reset370config_trigger_sync371read_firmwares $2372release_all_firmware373echo "OK"374}375376test_batched_request_firmware_into_buf()377{378echo -n "Batched request_firmware_into_buf() $2 try #$1: "379config_reset380config_set_name $TEST_FIRMWARE_INTO_BUF_FILENAME381config_set_into_buf382config_trigger_sync383read_firmwares $2384release_all_firmware385echo "OK"386}387388test_batched_request_firmware_direct()389{390echo -n "Batched request_firmware_direct() $2 try #$1: "391config_reset392config_set_sync_direct393config_trigger_sync394release_all_firmware395echo "OK"396}397398test_request_firmware_nowait_uevent()399{400echo -n "Batched request_firmware_nowait(uevent=true) $2 try #$1: "401config_reset402config_trigger_async403release_all_firmware404echo "OK"405}406407test_request_firmware_nowait_custom()408{409echo -n "Batched request_firmware_nowait(uevent=false) $2 try #$1: "410config_reset411config_unset_uevent412RANDOM_FILE_PATH=$(setup_random_file)413RANDOM_FILE="$(basename $RANDOM_FILE_PATH)"414if [ -n "$2" -a "$2" != "normal" ]; then415compress_"$2"_"$COMPRESS_FORMAT" $RANDOM_FILE_PATH416fi417config_set_name $RANDOM_FILE418config_trigger_async419release_all_firmware420echo "OK"421}422423test_request_partial_firmware_into_buf()424{425echo -n "Test request_partial_firmware_into_buf() off=$1 size=$2: "426config_reset427config_set_name $TEST_FIRMWARE_INTO_BUF_FILENAME428config_set_into_buf429config_set_partial430config_set_buf_size $2431config_set_file_offset $1432config_trigger_sync433read_partial_firmwares normal $1 $2434release_all_firmware435echo "OK"436}437438do_tests ()439{440mode="$1"441suffix="$2"442443for i in $(seq 1 5); do444test_batched_request_firmware$suffix $i $mode445done446447for i in $(seq 1 5); do448test_batched_request_firmware_into_buf$suffix $i $mode449done450451for i in $(seq 1 5); do452test_batched_request_firmware_direct$suffix $i $mode453done454455for i in $(seq 1 5); do456test_request_firmware_nowait_uevent$suffix $i $mode457done458459for i in $(seq 1 5); do460test_request_firmware_nowait_custom$suffix $i $mode461done462}463464# Only continue if batched request triggers are present on the465# test-firmware driver466test_config_present467468# test with the file present469echo470echo "Testing with the file present..."471do_tests normal472473# Partial loads cannot use fallback, so do not repeat tests.474test_request_partial_firmware_into_buf 0 10475test_request_partial_firmware_into_buf 0 5476test_request_partial_firmware_into_buf 1 6477test_request_partial_firmware_into_buf 2 10478479# Test for file not found, errors are expected, the failure would be480# a hung task, which would require a hard reset.481echo482echo "Testing with the file missing..."483do_tests nofile _nofile484485# Partial loads cannot use fallback, so do not repeat tests.486test_request_partial_firmware_into_buf_nofile 0 10487test_request_partial_firmware_into_buf_nofile 0 5488test_request_partial_firmware_into_buf_nofile 1 6489test_request_partial_firmware_into_buf_nofile 2 10490491test_request_firmware_compressed ()492{493export COMPRESS_FORMAT="$1"494495# test with both files present496compress_both_"$COMPRESS_FORMAT" $FW497compress_both_"$COMPRESS_FORMAT" $FW_INTO_BUF498499config_set_name $NAME500echo501echo "Testing with both plain and $COMPRESS_FORMAT files present..."502do_tests both503504# test with only compressed file present505mv "$FW" "${FW}-orig"506mv "$FW_INTO_BUF" "${FW_INTO_BUF}-orig"507508config_set_name $NAME509echo510echo "Testing with only $COMPRESS_FORMAT file present..."511do_tests componly512513mv "${FW}-orig" "$FW"514mv "${FW_INTO_BUF}-orig" "$FW_INTO_BUF"515}516517compress_both_XZ ()518{519$RUN_XZ -k "$@"520}521522compress_componly_XZ ()523{524$RUN_XZ "$@"525}526527compress_both_ZSTD ()528{529$RUN_ZSTD -k "$@"530}531532compress_componly_ZSTD ()533{534$RUN_ZSTD --rm "$@"535}536537if test "$HAS_FW_LOADER_COMPRESS_XZ" = "yes"; then538test_request_firmware_compressed XZ539fi540541if test "$HAS_FW_LOADER_COMPRESS_ZSTD" = "yes"; then542test_request_firmware_compressed ZSTD543fi544545exit 0546547548