123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- #!/bin/ash
- #(c) Copyright Barry Kauler Nov. 2010. License GPL v3 /usr/share/doc/legal
- #a complete rewrite of this script, aiming for extreme simplicity and multi-thread protection.
- #101202 usb_storage may have claimed an interface that is needed by another module (dual-mode 3G modems).
- #101202 more variability for random usleep.
- #101202 /etc/modules/firmware.dep.inst.${KERNVER} now has names of firmware tarballs, not modules.
- #101210 put files into /tmp/pup_event_backend (created by rc.sysinit).
- #101210 certain modules are loaded explicitly by /usr/sbin/usb_modeswitch_dispatcher.
- #101210 protect0, protect1, extra protection mechanisms. 101211: protect2.
- #101218 PREFLIST (in /etc/rc.d/MODULESCONFIG) format can have multiple ':', ex: 8139cp:8139too:8139xx (last is most preferred).
- #110508 do not allow argument-module if it is blacklisted (note blacklist.conf created in rc.sysinit).
- #110508 modprobe -i to ignore "install" and "remove" commands in /etc/modprobe.d/*.conf.
- #110509 avoid chance of a module not getting loaded when almost-simultaneous 'add' uevents.
- #110516 no longer using setup_alsa_func. now using /etc/modprobe.d/alsa-base.conf (from Ubuntu) only.
- #111106 support firmware directories.
- #120823 rerwin: $FIRMPKG always written.
- #120823 rerwin: --use-blacklist to apply the blacklist commands in the configuration files (if any) to module names as well.
- #120828 rerwin: --use-blacklist again.
- #120908 rerwin: Change preference processing to ensure preferred module loaded first.
- #120909 rerwin: Use temporary blacklisting for preferences to avoid interference and inconsistency.
- export LANG=C
- . /etc/rc.d/PUPSTATE
- . /etc/rc.d/MODULESCONFIG
- KERNVER="`uname -r`"
- [ "$FASTBOOTMODULESLIST" != "" ] && exit 1 #fastboot, see /etc/rc.d/MODULESCONFIG.
- #101121 rerwin: optional $1 supplied by triggered udev rule, see /etc/udev/rules.d/60-udev-modem.rules
- RULEMODULE=""
- [ $1 ] && RULEMODULE="$1"
- SLEEPU=`echo -n ${$} | rev` #110509 ex: pid 3124 becomes 4213, more variability for sleep.
- #setup_alsa_func() {
- # if [ "`echo $MODULE | cut -c 1-4`" = "snd_" ];then
- # while [ 1 ];do
- # CNTSND=`find /tmp/pup_event_backend -maxdepth 1 -type f -name 'pup_event_alsa_cnt*' | wc -l`
- # touch /tmp/pup_event_backend/pup_event_alsa_cnt${$}
- # tPATTERN='^alias snd\-card\-'"${CNTSND} "
- # #logic is a bit rough, but Alsa Wizard has already claimed this card...
- # [ "`grep "$tPATTERN" /etc/modprobe.d/alsa.conf`" != "" ] && continue
- # # note, /etc/modprobe.d/alsa_card*.conf is removed in rc.sysinit.
- # echo "alias snd-card-$CNTSND $MODULEx" > /etc/modprobe.d/alsa_card${$}.conf
- # echo "alias sound-slot-$CNTSND $MODULEx" >> /etc/modprobe.d/alsa_card${$}.conf
- # #paranoid check for two instances of this script clashing...
- # CNTSNDchk=`find /tmp/pup_event_backend -maxdepth 1 -type f -name 'pup_event_alsa_cnt*' | wc -l`
- # CNTSNDdiff=$(($CNTSNDchk - $CNTSND))
- # if [ $CNTSNDdiff -gt 1 ];then
- # rm -f /tmp/pup_event_backend/pup_event_alsa_cnt${$}
- # rm -f /etc/modprobe.d/alsa_card${$}.conf
- # #usleep ${$} #quasi random sleep.
- # #usleep `echo -n ${$} | rev` #101202 more variability.
- # usleep $SLEEPU #110509
- # continue
- # fi
- # break
- # done
- # fi
- #}
- firmware_tarball_func() {
- fPATTERN='[:,]'"${MODULE}"'\.ko|[:,]'"${MODULEx}"'\.ko'
- FIRMPKG="`cat /etc/modules/firmware.dep.${KERNVER} | grep -v '^#' | grep ':' | grep -E "$fPATTERN" | cut -f 1 -d ':' | head -n 1`"
- if [ "$FIRMPKG" != "" ];then
- iPATTERN='^'"${FIRMPKG}"'$'
- if [ "`grep "$iPATTERN" /etc/modules/firmware.dep.inst.${KERNVER}`" = "" ];then
- FLAGFIRM='no'
- if [ -d /lib/modules/all-firmware/${FIRMPKG} ];then #111106 support firmware directories.
- cp -a -f --remove-destination /lib/modules/all-firmware/${FIRMPKG}/* /
- FLAGFIRM='yes'
- else
- if [ -f /lib/modules/all-firmware/${FIRMPKG}.tar.gz ];then
- tar -z -x --strip=1 --directory=/ -f /lib/modules/all-firmware/${FIRMPKG}.tar.gz > /dev/null 2>&1
- FLAGFIRM='yes'
- fi
- fi
- if [ "$FLAGFIRM" = "yes" ];then
- #execute any post-install script...
- if [ -f /pinstall.${FIRMPKG}.sh ];then
- BRKCNT=0
- while [ 1 ];do #serialise execution of pinstall scripts...
- PINSTALLCNT=`find / -maxdepth 1 -type f -name 'pinstall.*.sh' | wc -l`
- [ $PINSTALLCNT -eq 1 ] && break
- usleep ${SLEEPU}0 #110509
- BRKCNT=$(($BRKCNT + 1))
- [ $BRKCNT -gt 5 ] && break
- done
- cd /
- /pinstall.${FIRMPKG}.sh >/dev/null 2>&1
- rm -f /pinstall.${FIRMPKG}.sh >/dev/null 2>&1
- fi
- echo "$FIRMPKG" >> /etc/modules/firmware.dep.inst.${KERNVER} #101202 120823 moved.
- fi
- fi
- fi
- }
- #120908...
- write_preference_log() {
- echo "$(date +%H:%M:%S.%N | cut -c 1-12) ${$} $MODULE - $1" >> /tmp/pup_event_backend/preferences.log
- }
- #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...
- ##101210 just in case this script called more than once with the same modalias...
- #echo "M=${MODALIAS} " > /tmp/pup_event_backend/protect0-${$}
- #mREGEX='M='"$MODALIAS"' '
- #[ `cat /tmp/pup_event_backend/protect0-* | grep "$mREGEX" | wc -l` -gt 1 ] && exit
- #note, no longer using /tmp/pup_event_modprobe.conf (which was created in rc.sysinit)...
- #110508 -i to ignore "install" and "remove" commands in /etc/modprobe.d/*.conf...
- #120823 rerwin: --use-blacklist (or -b) to apply the blacklist commands in the configuration files (if any) to module names as well...
- 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 '\-' '_'`"
- if [ "$RULEMODULE" != "" ];then
- if [ "$MODULE" = "" -o "$MODULE" = "usb_storage" -o "$MODULE" = "snd_hda_intel" ];then
- #110508 do not allow argument-module if it is blacklisted (note blacklist.conf created in rc.sysinit)...
- [ "`cat /etc/modprobe.d/blacklist*.conf | grep -w "${RULEMODULE}"`" = "" ] && MODULE="$RULEMODULE" #101121 rerwin: Use module from argument
- fi
- fi
- [ "$MODULE" = "" ] && exit 1
- #101202 usb_storage may have claimed an interface that is needed by another module (dual-mode 3G modems)...
- if [ "$MODULE" = "usb_storage" ];then
- if [ "`lsmod | grep '^usb_storage '`" != "" ];then
- if [ ! -f /etc/modprobe.d/blacklist-usb_storage.conf ];then
- echo 'blacklist usb_storage' > /etc/modprobe.d/blacklist-usb_storage.conf
- #120828 rerwin: --use-blacklist (or -b) to apply the blacklist commands in the configuration files (if any) to module names as well...
- 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
- [ "$MODULE" = "" ] && exit 1
- fi
- fi
- fi
- case $MODALIAS in
- pci:*)
- #######/etc/rc.d/MODULESCONFIG overrides######
- #may need to do substitution for specific pci interface...
- VENDOR='0x'"`echo -n "$MODALIAS" | cut -f 2 -d 'v' | cut -b 1-8 | tr [A-Z] [a-z]`"
- DEVICE='0x'"`echo -n "$MODALIAS" | cut -f 2 -d 'v' | cut -b 10-17 | tr [A-Z] [a-z]`"
- aPATTERN="$VENDOR $DEVICE"
- REPLACEMENT="`echo "$PCI_OVERRIDES" | grep "$aPATTERN" | cut -f 1 -d ' '`"
- [ "$REPLACEMENT" = "(none)" ] && exit 1
- #101121 rerwin: RULEMODULE: replace only if not already forced by udev rule...
- [ "$REPLACEMENT" != "" ] && [ "$RULEMODULE" = "" ] && MODULE="$REPLACEMENT"
- #####BAD HACKS SECTION#####
- if [ "$MODULE" = "mwave" ];then
- #only install firmware tarball, do not load module (firmware script does it).
- firmware_tarball_func
- exit 1
- fi
- ;;
- esac
- #101218 bugfix, improve...
- #preferences list, ex rt2500usb and rt73usb both hits, then choose latter...
- modPATTERN='^'"$MODULE"':'
- PREFHIT="`echo -n "$PREFLIST" | tr ' ' '\n' | grep "$modPATTERN" | head -n 1`" #120908
- if [ "$PREFHIT" != "" ];then
- origMODULE="$MODULE" #120908
- cat /etc/modprobe.d/* 2>/dev/null | grep -o '^blacklist *[^ ]*' | tr -s ' ' > /tmp/pup_event_backend/blacklist-$$.conf #120909
- PREFMODS="`echo -n "$PREFHIT" | cut -f 2-9 -d ':' | tr ':' ' '`"
- for PREFMOD in $PREFMODS #format can have multiple ':', ex: 8139cp:8139too:8139xx (last is most preferred).
- do
- echo "blacklist $MODULE" >> /tmp/pup_event_backend/blacklist-$$.conf #120909
- #120828 rerwin: --use-blacklist (or -b) to apply the blacklist commands in the configuration files (if any) to module names as well...
- 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
- [ "$xMODULE" = "$PREFMOD" ] && MODULE="$xMODULE"
- done
- rm -f /tmp/pup_event_backend/blacklist-$$.conf #120909
- [ "$MODULE" = "$origMODULE" ] \
- && sleep 1 \
- && write_preference_log "Retained ($PREFHIT)" \
- || write_preference_log "Substituted for module $origMODULE ($PREFHIT)" #120908
- fi
- #module already loaded, exit...
- mREGEX='MODULE='"$MODULE"' DEVPATH'
- if cat /tmp/pup_event_backend/pup_event_module_devpath_log* 2>/dev/null | grep "${mREGEX}" ;then exit ;fi
- ##101210 there may be virtual-simultaneous executions of this script to load the same module...
- #echo "M=${MODULE} " > /tmp/pup_event_backend/protect1-${$}
- #mREGEX='M='"$MODULE"' '
- #[ `cat /tmp/pup_event_backend/protect1-* | grep "$mREGEX" | wc -l` -gt 1 ] && exit
- ##...note: leaving out the above protect1 does not break anything, although it might potentially
- ## do so. Putting it in reduced execution past this point (on my laptop) from 54 to 25 times.
- ##101211 it is (remotely) possible simultaneous execution on a multi-core cpu could get past above, so...
- #usleep `echo -n ${$} | rev`0 #ex: 4123 would become 32140 microseconds.
- #echo "M=${MODULE} " > /tmp/pup_event_backend/protect2-${$}
- #[ `cat /tmp/pup_event_backend/protect2-* | grep "$mREGEX" | wc -l` -gt 1 ] && exit
- #110509 there may be almost-simultaneous executions of this script to load the same module...
- touch /tmp/pup_event_backend/lock1-${$} #start lock region.
- mREGEX=" ${MODULE} "
- echo "${$} ${MODULE} " > /tmp/pup_event_backend/protect1-${$}
- for NUM in 1 2
- do
- SIMULT="`cat /tmp/pup_event_backend/protect1-* | grep "${mREGEX}"`"
- [ $NUM -eq 1 ] && usleep ${SLEEPU}
- if [ `echo "$SIMULT" | wc -l` -gt 1 ];then
- [ $NUM -eq 2 ] && usleep ${SLEEPU}
- #random sleep above means that this process will kill the others before they can kill this one...
- for ONEPID in `echo -n "$SIMULT" | cut -f 1 -d ' ' | tr '\n' ' '`
- do
- [ $ONEPID -eq ${$} ] && continue
- [ -f /tmp/pup_event_backend/lock1-${ONEPID} ] && kill $ONEPID #other process within lock region.
- [ $? -eq 0 ] && rm -f /tmp/pup_event_backend/protect1-${ONEPID} && rm -f /tmp/pup_event_backend/lock1-${ONEPID}
- done
- fi
- done
- #if another process is beyond this point (loading same module), then exit here...
- rm -f /tmp/pup_event_backend/lock1-${$} && \
- [ `cat /tmp/pup_event_backend/protect1-* | grep "$mREGEX" | wc -l` -gt 1 ] && \
- rm -f /tmp/pup_event_backend/protect1-${$} && exit
- MODULEx="`echo -n "$MODULE" | tr '_' '-'`"
- #101210 certain modules are loaded explicitly by /usr/sbin/usb_modeswitch_dispatcher.
- #note, see also /usr/sbin/pupdial_init_hotpluggable, which can replay uevents and trigger usb_modeswitch_dispatcher.
- #i did put code in here to exit if comes here with MODULE==option (for example), but there does not seem
- #to be any clash, and for 3G modems that do not require switching (and hence usb_modeswitch does not run),
- #then it is necessary for the module to be loaded here.
- #110516 no longer using setup_alsa_func...
- #setup_alsa_func
- firmware_tarball_func
- #log to file. rc.sysinit needs this info to find out if any modaliases missed (also above)...
- echo "MODULE=$MODULE DEVPATH=$DEVPATH MODALIAS=$MODALIAS" >> /tmp/pup_event_backend/pup_event_module_devpath_log${$}
- cd /sbin #v408 rerwin thinks this is needed for slamr module.
- #120908 Wait for any preference processing, then ensure a preferred module is loaded first and any active conflicting modules afterward...
- if [ "$(ls /tmp/pup_event_backend/preference_processing_active* 2>/dev/null)" != "" ];then
- write_preference_log "Began waiting for preference processing"
- BRKCNT=0
- while [ $BRKCNT -lt 20 ]; do
- sleep 0.1
- BRKCNT=$(($BRKCNT + 1))
- [ "$(ls /tmp/pup_event_backend/preference_processing_active* 2>/dev/null)" = "" ] && break
- done
- write_preference_log "Resumed loading after preference processing"
- fi
- NONPREFS="$(echo -n "$PREFLIST" | tr ' ' '\n' | grep -w -o ".*:${MODULE}$" | sed -e 's/:[^:]*$//' | tr : '\n')"
- [ "$NONPREFS" = "" ] \
- || [ "$(lsmod | sed 's/ .*//' | grep -E "$(echo $MODULE $NONPREFS | tr ' ' '|')" | tail -n 1 | sed "s/^${MODULE}$//")" = "" ] \
- && exec /sbin/modprobe $MODULE
- touch /tmp/pup_event_backend/preference_processing_active-${$}
- write_preference_log "Began preference reload processing"
- NPRELOADS=""
- ALLDEPENDERS=""
- for ONEMODULE in $NONPREFS;do
- LOADEDNP="$(lsmod | grep "^$ONEMODULE ")"
- if [ "$LOADEDNP" = "" ];then
- LOADEDNP="$(grep -o "^MODULE=${ONEMODULE} " /tmp/pup_event_backend/pup_event_module_devpath_log* | grep -o '[^=]*$')"
- DEPENDERS=""
- else
- DEPENDERS="$(echo -n $LOADEDNP | tr -s ' ' | cut -f 4 -d ' ' | tr -d - | tr , ' ' | tr '\n' ' ' | sed 's/^ *$//')"
- fi
- if [ "$LOADEDNP" != "" ];then
- if [ "$DEPENDERS" != "" ];then
- /sbin/modprobe -r -i -q $DEPENDERS
- wait
- ALLDEPENDERS="${ALLDEPENDERS}${DEPENDERS}"
- fi
- /sbin/modprobe -r -i -q $ONEMODULE
- wait
- NPRELOADS="${ONEMODULE} ${NPRELOADS}" #reverse order
- fi
- done
- for ONEMODULE in $MODULE $NPRELOADS $ALLDEPENDERS;do
- lsmod | grep -q -w "^$ONEMODULE" \
- && [ "$ONEMODULE" != "$MODULE" ] \
- && write_preference_log "Unload failed for module: ${ONEMODULE}"
- /sbin/modprobe $ONEMODULE
- sleep 0.01 #precaution
- done
- write_preference_log "Reloaded module(s): ${NPRELOADS}${ALLDEPENDERS}"
- rm -f /tmp/pup_event_backend/preference_processing_active-${$}
- #120908 end
- ###END###
|