pup_event_backend_modprobe 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. #!/bin/ash
  2. #(c) Copyright Barry Kauler Nov. 2010. License GPL v3 /usr/share/doc/legal
  3. #a complete rewrite of this script, aiming for extreme simplicity and multi-thread protection.
  4. #101202 usb_storage may have claimed an interface that is needed by another module (dual-mode 3G modems).
  5. #101202 more variability for random usleep.
  6. #101202 /etc/modules/firmware.dep.inst.${KERNVER} now has names of firmware tarballs, not modules.
  7. #101210 put files into /tmp/pup_event_backend (created by rc.sysinit).
  8. #101210 certain modules are loaded explicitly by /usr/sbin/usb_modeswitch_dispatcher.
  9. #101210 protect0, protect1, extra protection mechanisms. 101211: protect2.
  10. #101218 PREFLIST (in /etc/rc.d/MODULESCONFIG) format can have multiple ':', ex: 8139cp:8139too:8139xx (last is most preferred).
  11. #110508 do not allow argument-module if it is blacklisted (note blacklist.conf created in rc.sysinit).
  12. #110508 modprobe -i to ignore "install" and "remove" commands in /etc/modprobe.d/*.conf.
  13. #110509 avoid chance of a module not getting loaded when almost-simultaneous 'add' uevents.
  14. #110516 no longer using setup_alsa_func. now using /etc/modprobe.d/alsa-base.conf (from Ubuntu) only.
  15. #111106 support firmware directories.
  16. #120823 rerwin: $FIRMPKG always written.
  17. #120823 rerwin: --use-blacklist to apply the blacklist commands in the configuration files (if any) to module names as well.
  18. #120828 rerwin: --use-blacklist again.
  19. #120908 rerwin: Change preference processing to ensure preferred module loaded first.
  20. #120909 rerwin: Use temporary blacklisting for preferences to avoid interference and inconsistency.
  21. export LANG=C
  22. . /etc/rc.d/PUPSTATE
  23. . /etc/rc.d/MODULESCONFIG
  24. KERNVER="`uname -r`"
  25. [ "$FASTBOOTMODULESLIST" != "" ] && exit 1 #fastboot, see /etc/rc.d/MODULESCONFIG.
  26. #101121 rerwin: optional $1 supplied by triggered udev rule, see /etc/udev/rules.d/60-udev-modem.rules
  27. RULEMODULE=""
  28. [ $1 ] && RULEMODULE="$1"
  29. SLEEPU=`echo -n ${$} | rev` #110509 ex: pid 3124 becomes 4213, more variability for sleep.
  30. #setup_alsa_func() {
  31. # if [ "`echo $MODULE | cut -c 1-4`" = "snd_" ];then
  32. # while [ 1 ];do
  33. # CNTSND=`find /tmp/pup_event_backend -maxdepth 1 -type f -name 'pup_event_alsa_cnt*' | wc -l`
  34. # touch /tmp/pup_event_backend/pup_event_alsa_cnt${$}
  35. # tPATTERN='^alias snd\-card\-'"${CNTSND} "
  36. # #logic is a bit rough, but Alsa Wizard has already claimed this card...
  37. # [ "`grep "$tPATTERN" /etc/modprobe.d/alsa.conf`" != "" ] && continue
  38. # # note, /etc/modprobe.d/alsa_card*.conf is removed in rc.sysinit.
  39. # echo "alias snd-card-$CNTSND $MODULEx" > /etc/modprobe.d/alsa_card${$}.conf
  40. # echo "alias sound-slot-$CNTSND $MODULEx" >> /etc/modprobe.d/alsa_card${$}.conf
  41. # #paranoid check for two instances of this script clashing...
  42. # CNTSNDchk=`find /tmp/pup_event_backend -maxdepth 1 -type f -name 'pup_event_alsa_cnt*' | wc -l`
  43. # CNTSNDdiff=$(($CNTSNDchk - $CNTSND))
  44. # if [ $CNTSNDdiff -gt 1 ];then
  45. # rm -f /tmp/pup_event_backend/pup_event_alsa_cnt${$}
  46. # rm -f /etc/modprobe.d/alsa_card${$}.conf
  47. # #usleep ${$} #quasi random sleep.
  48. # #usleep `echo -n ${$} | rev` #101202 more variability.
  49. # usleep $SLEEPU #110509
  50. # continue
  51. # fi
  52. # break
  53. # done
  54. # fi
  55. #}
  56. firmware_tarball_func() {
  57. fPATTERN='[:,]'"${MODULE}"'\.ko|[:,]'"${MODULEx}"'\.ko'
  58. FIRMPKG="`cat /etc/modules/firmware.dep.${KERNVER} | grep -v '^#' | grep ':' | grep -E "$fPATTERN" | cut -f 1 -d ':' | head -n 1`"
  59. if [ "$FIRMPKG" != "" ];then
  60. iPATTERN='^'"${FIRMPKG}"'$'
  61. if [ "`grep "$iPATTERN" /etc/modules/firmware.dep.inst.${KERNVER}`" = "" ];then
  62. FLAGFIRM='no'
  63. if [ -d /lib/modules/all-firmware/${FIRMPKG} ];then #111106 support firmware directories.
  64. cp -a -f --remove-destination /lib/modules/all-firmware/${FIRMPKG}/* /
  65. FLAGFIRM='yes'
  66. else
  67. if [ -f /lib/modules/all-firmware/${FIRMPKG}.tar.gz ];then
  68. tar -z -x --strip=1 --directory=/ -f /lib/modules/all-firmware/${FIRMPKG}.tar.gz > /dev/null 2>&1
  69. FLAGFIRM='yes'
  70. fi
  71. fi
  72. if [ "$FLAGFIRM" = "yes" ];then
  73. #execute any post-install script...
  74. if [ -f /pinstall.${FIRMPKG}.sh ];then
  75. BRKCNT=0
  76. while [ 1 ];do #serialise execution of pinstall scripts...
  77. PINSTALLCNT=`find / -maxdepth 1 -type f -name 'pinstall.*.sh' | wc -l`
  78. [ $PINSTALLCNT -eq 1 ] && break
  79. usleep ${SLEEPU}0 #110509
  80. BRKCNT=$(($BRKCNT + 1))
  81. [ $BRKCNT -gt 5 ] && break
  82. done
  83. cd /
  84. /pinstall.${FIRMPKG}.sh >/dev/null 2>&1
  85. rm -f /pinstall.${FIRMPKG}.sh >/dev/null 2>&1
  86. fi
  87. echo "$FIRMPKG" >> /etc/modules/firmware.dep.inst.${KERNVER} #101202 120823 moved.
  88. fi
  89. fi
  90. fi
  91. }
  92. #120908...
  93. write_preference_log() {
  94. echo "$(date +%H:%M:%S.%N | cut -c 1-12) ${$} $MODULE - $1" >> /tmp/pup_event_backend/preferences.log
  95. }
  96. #101210 remove. multiple entries with same modalias may be required, for example 3G modem that needs to load usb-storage and option on same interface...
  97. ##101210 just in case this script called more than once with the same modalias...
  98. #echo "M=${MODALIAS} " > /tmp/pup_event_backend/protect0-${$}
  99. #mREGEX='M='"$MODALIAS"' '
  100. #[ `cat /tmp/pup_event_backend/protect0-* | grep "$mREGEX" | wc -l` -gt 1 ] && exit
  101. #note, no longer using /tmp/pup_event_modprobe.conf (which was created in rc.sysinit)...
  102. #110508 -i to ignore "install" and "remove" commands in /etc/modprobe.d/*.conf...
  103. #120823 rerwin: --use-blacklist (or -b) to apply the blacklist commands in the configuration files (if any) to module names as well...
  104. MODULE="`/sbin/modprobe -i --use-blacklist --show-depends $MODALIAS 2>/dev/null | tail -n 1 | rev | cut -f 1 -d '/' | rev | cut -f 1 -d '.' | tr '\-' '_'`"
  105. if [ "$RULEMODULE" != "" ];then
  106. if [ "$MODULE" = "" -o "$MODULE" = "usb_storage" -o "$MODULE" = "snd_hda_intel" ];then
  107. #110508 do not allow argument-module if it is blacklisted (note blacklist.conf created in rc.sysinit)...
  108. [ "`cat /etc/modprobe.d/blacklist*.conf | grep -w "${RULEMODULE}"`" = "" ] && MODULE="$RULEMODULE" #101121 rerwin: Use module from argument
  109. fi
  110. fi
  111. [ "$MODULE" = "" ] && exit 1
  112. #101202 usb_storage may have claimed an interface that is needed by another module (dual-mode 3G modems)...
  113. if [ "$MODULE" = "usb_storage" ];then
  114. if [ "`lsmod | grep '^usb_storage '`" != "" ];then
  115. if [ ! -f /etc/modprobe.d/blacklist-usb_storage.conf ];then
  116. echo 'blacklist usb_storage' > /etc/modprobe.d/blacklist-usb_storage.conf
  117. #120828 rerwin: --use-blacklist (or -b) to apply the blacklist commands in the configuration files (if any) to module names as well...
  118. MODULE="`/sbin/modprobe -i --use-blacklist --show-depends $MODALIAS 2>/dev/null | tail -n 1 | rev | cut -f 1 -d '/' | rev | cut -f 1 -d '.' | tr '\-' '_'`" #110508 120828
  119. [ "$MODULE" = "" ] && exit 1
  120. fi
  121. fi
  122. fi
  123. case $MODALIAS in
  124. pci:*)
  125. #######/etc/rc.d/MODULESCONFIG overrides######
  126. #may need to do substitution for specific pci interface...
  127. VENDOR='0x'"`echo -n "$MODALIAS" | cut -f 2 -d 'v' | cut -b 1-8 | tr [A-Z] [a-z]`"
  128. DEVICE='0x'"`echo -n "$MODALIAS" | cut -f 2 -d 'v' | cut -b 10-17 | tr [A-Z] [a-z]`"
  129. aPATTERN="$VENDOR $DEVICE"
  130. REPLACEMENT="`echo "$PCI_OVERRIDES" | grep "$aPATTERN" | cut -f 1 -d ' '`"
  131. [ "$REPLACEMENT" = "(none)" ] && exit 1
  132. #101121 rerwin: RULEMODULE: replace only if not already forced by udev rule...
  133. [ "$REPLACEMENT" != "" ] && [ "$RULEMODULE" = "" ] && MODULE="$REPLACEMENT"
  134. #####BAD HACKS SECTION#####
  135. if [ "$MODULE" = "mwave" ];then
  136. #only install firmware tarball, do not load module (firmware script does it).
  137. firmware_tarball_func
  138. exit 1
  139. fi
  140. ;;
  141. esac
  142. #101218 bugfix, improve...
  143. #preferences list, ex rt2500usb and rt73usb both hits, then choose latter...
  144. modPATTERN='^'"$MODULE"':'
  145. PREFHIT="`echo -n "$PREFLIST" | tr ' ' '\n' | grep "$modPATTERN" | head -n 1`" #120908
  146. if [ "$PREFHIT" != "" ];then
  147. origMODULE="$MODULE" #120908
  148. cat /etc/modprobe.d/* 2>/dev/null | grep -o '^blacklist *[^ ]*' | tr -s ' ' > /tmp/pup_event_backend/blacklist-$$.conf #120909
  149. PREFMODS="`echo -n "$PREFHIT" | cut -f 2-9 -d ':' | tr ':' ' '`"
  150. for PREFMOD in $PREFMODS #format can have multiple ':', ex: 8139cp:8139too:8139xx (last is most preferred).
  151. do
  152. echo "blacklist $MODULE" >> /tmp/pup_event_backend/blacklist-$$.conf #120909
  153. #120828 rerwin: --use-blacklist (or -b) to apply the blacklist commands in the configuration files (if any) to module names as well...
  154. xMODULE="`/sbin/modprobe -i --use-blacklist --config /tmp/pup_event_backend/blacklist-$$.conf --show-depends $MODALIAS 2>/dev/null | tail -n 1 | rev | cut -f 1 -d '/' | rev | cut -f 1 -d '.' | tr '\-' '_'`" #110508 120828 120909
  155. [ "$xMODULE" = "$PREFMOD" ] && MODULE="$xMODULE"
  156. done
  157. rm -f /tmp/pup_event_backend/blacklist-$$.conf #120909
  158. [ "$MODULE" = "$origMODULE" ] \
  159. && sleep 1 \
  160. && write_preference_log "Retained ($PREFHIT)" \
  161. || write_preference_log "Substituted for module $origMODULE ($PREFHIT)" #120908
  162. fi
  163. #module already loaded, exit...
  164. mREGEX='MODULE='"$MODULE"' DEVPATH'
  165. if cat /tmp/pup_event_backend/pup_event_module_devpath_log* 2>/dev/null | grep "${mREGEX}" ;then exit ;fi
  166. ##101210 there may be virtual-simultaneous executions of this script to load the same module...
  167. #echo "M=${MODULE} " > /tmp/pup_event_backend/protect1-${$}
  168. #mREGEX='M='"$MODULE"' '
  169. #[ `cat /tmp/pup_event_backend/protect1-* | grep "$mREGEX" | wc -l` -gt 1 ] && exit
  170. ##...note: leaving out the above protect1 does not break anything, although it might potentially
  171. ## do so. Putting it in reduced execution past this point (on my laptop) from 54 to 25 times.
  172. ##101211 it is (remotely) possible simultaneous execution on a multi-core cpu could get past above, so...
  173. #usleep `echo -n ${$} | rev`0 #ex: 4123 would become 32140 microseconds.
  174. #echo "M=${MODULE} " > /tmp/pup_event_backend/protect2-${$}
  175. #[ `cat /tmp/pup_event_backend/protect2-* | grep "$mREGEX" | wc -l` -gt 1 ] && exit
  176. #110509 there may be almost-simultaneous executions of this script to load the same module...
  177. touch /tmp/pup_event_backend/lock1-${$} #start lock region.
  178. mREGEX=" ${MODULE} "
  179. echo "${$} ${MODULE} " > /tmp/pup_event_backend/protect1-${$}
  180. for NUM in 1 2
  181. do
  182. SIMULT="`cat /tmp/pup_event_backend/protect1-* | grep "${mREGEX}"`"
  183. [ $NUM -eq 1 ] && usleep ${SLEEPU}
  184. if [ `echo "$SIMULT" | wc -l` -gt 1 ];then
  185. [ $NUM -eq 2 ] && usleep ${SLEEPU}
  186. #random sleep above means that this process will kill the others before they can kill this one...
  187. for ONEPID in `echo -n "$SIMULT" | cut -f 1 -d ' ' | tr '\n' ' '`
  188. do
  189. [ $ONEPID -eq ${$} ] && continue
  190. [ -f /tmp/pup_event_backend/lock1-${ONEPID} ] && kill $ONEPID #other process within lock region.
  191. [ $? -eq 0 ] && rm -f /tmp/pup_event_backend/protect1-${ONEPID} && rm -f /tmp/pup_event_backend/lock1-${ONEPID}
  192. done
  193. fi
  194. done
  195. #if another process is beyond this point (loading same module), then exit here...
  196. rm -f /tmp/pup_event_backend/lock1-${$} && \
  197. [ `cat /tmp/pup_event_backend/protect1-* | grep "$mREGEX" | wc -l` -gt 1 ] && \
  198. rm -f /tmp/pup_event_backend/protect1-${$} && exit
  199. MODULEx="`echo -n "$MODULE" | tr '_' '-'`"
  200. #101210 certain modules are loaded explicitly by /usr/sbin/usb_modeswitch_dispatcher.
  201. #note, see also /usr/sbin/pupdial_init_hotpluggable, which can replay uevents and trigger usb_modeswitch_dispatcher.
  202. #i did put code in here to exit if comes here with MODULE==option (for example), but there does not seem
  203. #to be any clash, and for 3G modems that do not require switching (and hence usb_modeswitch does not run),
  204. #then it is necessary for the module to be loaded here.
  205. #110516 no longer using setup_alsa_func...
  206. #setup_alsa_func
  207. firmware_tarball_func
  208. #log to file. rc.sysinit needs this info to find out if any modaliases missed (also above)...
  209. echo "MODULE=$MODULE DEVPATH=$DEVPATH MODALIAS=$MODALIAS" >> /tmp/pup_event_backend/pup_event_module_devpath_log${$}
  210. cd /sbin #v408 rerwin thinks this is needed for slamr module.
  211. #120908 Wait for any preference processing, then ensure a preferred module is loaded first and any active conflicting modules afterward...
  212. if [ "$(ls /tmp/pup_event_backend/preference_processing_active* 2>/dev/null)" != "" ];then
  213. write_preference_log "Began waiting for preference processing"
  214. BRKCNT=0
  215. while [ $BRKCNT -lt 20 ]; do
  216. sleep 0.1
  217. BRKCNT=$(($BRKCNT + 1))
  218. [ "$(ls /tmp/pup_event_backend/preference_processing_active* 2>/dev/null)" = "" ] && break
  219. done
  220. write_preference_log "Resumed loading after preference processing"
  221. fi
  222. NONPREFS="$(echo -n "$PREFLIST" | tr ' ' '\n' | grep -w -o ".*:${MODULE}$" | sed -e 's/:[^:]*$//' | tr : '\n')"
  223. [ "$NONPREFS" = "" ] \
  224. || [ "$(lsmod | sed 's/ .*//' | grep -E "$(echo $MODULE $NONPREFS | tr ' ' '|')" | tail -n 1 | sed "s/^${MODULE}$//")" = "" ] \
  225. && exec /sbin/modprobe $MODULE
  226. touch /tmp/pup_event_backend/preference_processing_active-${$}
  227. write_preference_log "Began preference reload processing"
  228. NPRELOADS=""
  229. ALLDEPENDERS=""
  230. for ONEMODULE in $NONPREFS;do
  231. LOADEDNP="$(lsmod | grep "^$ONEMODULE ")"
  232. if [ "$LOADEDNP" = "" ];then
  233. LOADEDNP="$(grep -o "^MODULE=${ONEMODULE} " /tmp/pup_event_backend/pup_event_module_devpath_log* | grep -o '[^=]*$')"
  234. DEPENDERS=""
  235. else
  236. DEPENDERS="$(echo -n $LOADEDNP | tr -s ' ' | cut -f 4 -d ' ' | tr -d - | tr , ' ' | tr '\n' ' ' | sed 's/^ *$//')"
  237. fi
  238. if [ "$LOADEDNP" != "" ];then
  239. if [ "$DEPENDERS" != "" ];then
  240. /sbin/modprobe -r -i -q $DEPENDERS
  241. wait
  242. ALLDEPENDERS="${ALLDEPENDERS}${DEPENDERS}"
  243. fi
  244. /sbin/modprobe -r -i -q $ONEMODULE
  245. wait
  246. NPRELOADS="${ONEMODULE} ${NPRELOADS}" #reverse order
  247. fi
  248. done
  249. for ONEMODULE in $MODULE $NPRELOADS $ALLDEPENDERS;do
  250. lsmod | grep -q -w "^$ONEMODULE" \
  251. && [ "$ONEMODULE" != "$MODULE" ] \
  252. && write_preference_log "Unload failed for module: ${ONEMODULE}"
  253. /sbin/modprobe $ONEMODULE
  254. sleep 0.01 #precaution
  255. done
  256. write_preference_log "Reloaded module(s): ${NPRELOADS}${ALLDEPENDERS}"
  257. rm -f /tmp/pup_event_backend/preference_processing_active-${$}
  258. #120908 end
  259. ###END###