#!/bin/sh # This validates that the kernel will load firmware out of its list of # firmware locations on disk. Since the user helper does similar work, # we reset the custom load directory to a location the user helper doesn't # know so we can be sure we're not accidentally testing the user helper. set -e modprobe test_firmware global DIR := '/sys/devices/virtual/misc/test_firmware' # CONFIG_FW_LOADER_USER_HELPER has a sysfs class under /sys/class/firmware/ # These days no one enables CONFIG_FW_LOADER_USER_HELPER so check for that # as an indicator for CONFIG_FW_LOADER_USER_HELPER. global HAS_FW_LOADER_USER_HELPER := $[if test -d /sys/class/firmware/ { echo yes; } else { echo no; }] if test $HAS_FW_LOADER_USER_HELPER = "yes" { global OLD_TIMEOUT := $[cat /sys/class/firmware/timeout] } global OLD_FWPATH := $[cat /sys/module/firmware_class/parameters/path] global FWPATH := $[mktemp -d] global FW := ""$FWPATH/test-firmware.bin"" proc test_finish { if test $HAS_FW_LOADER_USER_HELPER = "yes" { echo $OLD_TIMEOUT >/sys/class/firmware/timeout } echo -n $OLD_PATH >/sys/module/firmware_class/parameters/path rm -f $FW rmdir $FWPATH } trap "test_finish" EXIT if test $HAS_FW_LOADER_USER_HELPER = "yes" { # Turn down the timeout so failures don't take so long. echo 1 >/sys/class/firmware/timeout } # Set the kernel search path. echo -n $FWPATH >/sys/module/firmware_class/parameters/path # This is an unlikely real-world firmware content. :) echo "ABCD0123" >$FW global NAME := $[basename $FW] if printf '\000' >"$DIR"/trigger_request { echo "$0: empty filename should not succeed" > !2 exit 1 } if printf '\000' >"$DIR"/trigger_async_request { echo "$0: empty filename should not succeed (async)" > !2 exit 1 } # Request a firmware that doesn't exist, it should fail. if echo -n "nope-$NAME" >"$DIR"/trigger_request { echo "$0: firmware shouldn't have loaded" > !2 exit 1 } if diff -q $FW /dev/test_firmware >/dev/null { echo "$0: firmware was not expected to match" > !2 exit 1 } else { if test $HAS_FW_LOADER_USER_HELPER = "yes" { echo "$0: timeout works" } } # This should succeed via kernel load or will fail after 1 second after # being handed over to the user helper, which won't find the fw either. if ! echo -n $NAME >"$DIR"/trigger_request { echo "$0: could not trigger request" > !2 exit 1 } # Verify the contents are what we expect. if ! diff -q $FW /dev/test_firmware >/dev/null { echo "$0: firmware was not loaded" > !2 exit 1 } else { echo "$0: filesystem loading works" } # Try the asynchronous version too if ! echo -n $NAME >"$DIR"/trigger_async_request { echo "$0: could not trigger async request" > !2 exit 1 } # Verify the contents are what we expect. if ! diff -q $FW /dev/test_firmware >/dev/null { echo "$0: firmware was not loaded (async)" > !2 exit 1 } else { echo "$0: async filesystem loading works" } exit 0 (CommandList children: [ (C {(set)} {(-e)}) (C {(modprobe)} {(test_firmware)}) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:DIR) op: Equal rhs: {(/sys/devices/virtual/misc/test_firmware)} spids: [25] ) ] spids: [25] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:HAS_FW_LOADER_USER_HELPER) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (If arms: [ (if_arm cond: [ (Sentence child: (C {(Lit_Other "[")} {(-d)} {(/sys/class/firmware/)} {(Lit_Other "]")}) terminator: ) ] action: [(Sentence child:(C {(echo)} {(yes)}) terminator:)] spids: [-1 51] ) ] else_action: [(Sentence child:(C {(echo)} {(no)}) terminator:)] spids: [58 65] ) ] ) left_token: spids: [39 66] ) } spids: [38] ) ] spids: [38] ) (If arms: [ (if_arm cond: [ (Sentence child: (C {(Lit_Other "[")} {(DQ ($ VSub_Name "$HAS_FW_LOADER_USER_HELPER"))} {(Lit_Other "=")} {(DQ (yes))} {(Lit_Other "]")} ) terminator: ) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:OLD_TIMEOUT) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [(C {(cat)} {(/sys/class/firmware/timeout)})] ) left_token: spids: [90 94] ) } spids: [89] ) ] spids: [89] ) ] spids: [-1 86] ) ] spids: [-1 96] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:OLD_FWPATH) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [(C {(cat)} {(/sys/module/firmware_class/parameters/path)})] ) left_token: spids: [100 104] ) } spids: [99] ) ] spids: [99] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:FWPATH) op: Equal rhs: { (CommandSubPart command_list: (CommandList children:[(C {(mktemp)} {(-d)})]) left_token: spids: [108 112] ) } spids: [107] ) ] spids: [107] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:FW) op: Equal rhs: {(DQ ($ VSub_Name "$FWPATH") (/test-firmware.bin))} spids: [114] ) ] spids: [114] ) (FuncDef name: test_finish body: (BraceGroup children: [ (If arms: [ (if_arm cond: [ (Sentence child: (C {(Lit_Other "[")} {(DQ ($ VSub_Name "$HAS_FW_LOADER_USER_HELPER"))} {(Lit_Other "=")} {(DQ (yes))} {(Lit_Other "]")} ) terminator: ) ] action: [ (SimpleCommand words: [{(echo)} {(DQ ($ VSub_Name "$OLD_TIMEOUT"))}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(/sys/class/firmware/timeout)} spids: [154] ) ] ) ] spids: [-1 145] ) ] spids: [-1 158] ) (SimpleCommand words: [{(echo)} {(-n)} {(DQ ($ VSub_Name "$OLD_PATH"))}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(/sys/module/firmware_class/parameters/path)} spids: [169] ) ] ) (C {(rm)} {(-f)} {(DQ ($ VSub_Name "$FW"))}) (C {(rmdir)} {(DQ ($ VSub_Name "$FWPATH"))}) ] spids: [125] ) spids: [121 124] ) (C {(trap)} {(DQ (test_finish))} {(EXIT)}) (If arms: [ (if_arm cond: [ (Sentence child: (C {(Lit_Other "[")} {(DQ ($ VSub_Name "$HAS_FW_LOADER_USER_HELPER"))} {(Lit_Other "=")} {(DQ (yes))} {(Lit_Other "]")} ) terminator: ) ] action: [ (SimpleCommand words: [{(echo)} {(1)}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(/sys/class/firmware/timeout)} spids: [228] ) ] ) ] spids: [-1 217] ) ] spids: [-1 231] ) (SimpleCommand words: [{(echo)} {(-n)} {(DQ ($ VSub_Name "$FWPATH"))}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(/sys/module/firmware_class/parameters/path)} spids: [245] ) ] ) (SimpleCommand words: [{(echo)} {(DQ (ABCD0123))}] redirects: [(Redir op_id:Redir_Great fd:-1 arg_word:{(DQ ($ VSub_Name "$FW"))} spids:[258])] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:NAME) op: Equal rhs: { (CommandSubPart command_list: (CommandList children:[(C {(basename)} {(DQ ($ VSub_Name "$FW"))})]) left_token: spids: [265 271] ) } spids: [264] ) ] spids: [264] ) (If arms: [ (if_arm cond: [ (Sentence child: (SimpleCommand words: [{(printf)} {(SQ <"\\000">)}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(DQ ($ VSub_Name "$DIR")) (/trigger_request)} spids: [282] ) ] ) terminator: ) ] action: [ (SimpleCommand words: [{(echo)} {(DQ ($ VSub_Number "$0") (": empty filename should not succeed"))}] redirects: [(Redir op_id:Redir_GreatAnd fd:-1 arg_word:{(2)} spids:[299])] ) (C {(exit)} {(1)}) ] spids: [-1 289] ) ] spids: [-1 307] ) (If arms: [ (if_arm cond: [ (Sentence child: (SimpleCommand words: [{(printf)} {(SQ <"\\000">)}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(DQ ($ VSub_Name "$DIR")) (/trigger_async_request)} spids: [318] ) ] ) terminator: ) ] action: [ (SimpleCommand words: [ {(echo)} {(DQ ($ VSub_Number "$0") (": empty filename should not succeed (async)"))} ] redirects: [(Redir op_id:Redir_GreatAnd fd:-1 arg_word:{(2)} spids:[335])] ) (C {(exit)} {(1)}) ] spids: [-1 325] ) ] spids: [-1 343] ) (If arms: [ (if_arm cond: [ (Sentence child: (SimpleCommand words: [{(echo)} {(-n)} {(DQ (nope-) ($ VSub_Name "$NAME"))}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(DQ ($ VSub_Name "$DIR")) (/trigger_request)} spids: [360] ) ] ) terminator: ) ] action: [ (SimpleCommand words: [{(echo)} {(DQ ($ VSub_Number "$0") (": firmware shouldn't have loaded"))}] redirects: [(Redir op_id:Redir_GreatAnd fd:-1 arg_word:{(2)} spids:[377])] ) (C {(exit)} {(1)}) ] spids: [-1 367] ) ] spids: [-1 385] ) (If arms: [ (if_arm cond: [ (Sentence child: (SimpleCommand words: [{(diff)} {(-q)} {(DQ ($ VSub_Name "$FW"))} {(/dev/test_firmware)}] redirects: [(Redir op_id:Redir_Great fd:-1 arg_word:{(/dev/null)} spids:[399])] ) terminator: ) ] action: [ (SimpleCommand words: [{(echo)} {(DQ ($ VSub_Number "$0") (": firmware was not expected to match"))}] redirects: [(Redir op_id:Redir_GreatAnd fd:-1 arg_word:{(2)} spids:[414])] ) (C {(exit)} {(1)}) ] spids: [-1 404] ) ] else_action: [ (If arms: [ (if_arm cond: [ (Sentence child: (C {(Lit_Other "[")} {(DQ ($ VSub_Name "$HAS_FW_LOADER_USER_HELPER"))} {(Lit_Other "=")} {(DQ (yes))} {(Lit_Other "]")} ) terminator: ) ] action: [(C {(echo)} {(DQ ($ VSub_Number "$0") (": timeout works"))})] spids: [-1 442] ) ] spids: [-1 453] ) ] spids: [422 455] ) (If arms: [ (if_arm cond: [ (Sentence child: (Pipeline children: [ (SimpleCommand words: [{(echo)} {(-n)} {(DQ ($ VSub_Name "$NAME"))}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(DQ ($ VSub_Name "$DIR")) (/trigger_request)} spids: [476] ) ] ) ] negated: True ) terminator: ) ] action: [ (SimpleCommand words: [{(echo)} {(DQ ($ VSub_Number "$0") (": could not trigger request"))}] redirects: [(Redir op_id:Redir_GreatAnd fd:-1 arg_word:{(2)} spids:[494])] ) (C {(exit)} {(1)}) ] spids: [-1 484] ) ] spids: [-1 502] ) (If arms: [ (if_arm cond: [ (Sentence child: (Pipeline children: [ (SimpleCommand words: [{(diff)} {(-q)} {(DQ ($ VSub_Name "$FW"))} {(/dev/test_firmware)}] redirects: [(Redir op_id:Redir_Great fd:-1 arg_word:{(/dev/null)} spids:[522])] ) ] negated: True ) terminator: ) ] action: [ (SimpleCommand words: [{(echo)} {(DQ ($ VSub_Number "$0") (": firmware was not loaded"))}] redirects: [(Redir op_id:Redir_GreatAnd fd:-1 arg_word:{(2)} spids:[537])] ) (C {(exit)} {(1)}) ] spids: [-1 527] ) ] else_action: [(C {(echo)} {(DQ ($ VSub_Number "$0") (": filesystem loading works"))})] spids: [545 555] ) (If arms: [ (if_arm cond: [ (Sentence child: (Pipeline children: [ (SimpleCommand words: [{(echo)} {(-n)} {(DQ ($ VSub_Name "$NAME"))}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(DQ ($ VSub_Name "$DIR")) (/trigger_async_request)} spids: [573] ) ] ) ] negated: True ) terminator: ) ] action: [ (SimpleCommand words: [{(echo)} {(DQ ($ VSub_Number "$0") (": could not trigger async request"))}] redirects: [(Redir op_id:Redir_GreatAnd fd:-1 arg_word:{(2)} spids:[591])] ) (C {(exit)} {(1)}) ] spids: [-1 581] ) ] spids: [-1 599] ) (If arms: [ (if_arm cond: [ (Sentence child: (Pipeline children: [ (SimpleCommand words: [{(diff)} {(-q)} {(DQ ($ VSub_Name "$FW"))} {(/dev/test_firmware)}] redirects: [(Redir op_id:Redir_Great fd:-1 arg_word:{(/dev/null)} spids:[619])] ) ] negated: True ) terminator: ) ] action: [ (SimpleCommand words: [{(echo)} {(DQ ($ VSub_Number "$0") (": firmware was not loaded (async)"))}] redirects: [(Redir op_id:Redir_GreatAnd fd:-1 arg_word:{(2)} spids:[634])] ) (C {(exit)} {(1)}) ] spids: [-1 624] ) ] else_action: [(C {(echo)} {(DQ ($ VSub_Number "$0") (": async filesystem loading works"))})] spids: [642 652] ) (C {(exit)} {(0)}) ] )