#!/bin/sh ## pnp modules bootloader v0.29 ## (c) Denis Kaganovich, under Anarchy license ## consume preprocessed /lib/modules/$KV/modules.alias [ -z "$TMPDIR" ] && [ -e /temp ] && TMPDIR=/temp ## millisecons #SYS_FIND=/sys SYS_FIND=/sys/devices uFIND="find $SYS_FIND -xdev -name uevent" SAVE_HOTPLUG=- export blkid_cache=/etc/blkid.sh.cache pids= onbatt=false TRYOPT=0 etest(){ local x x=`(eval "$1") 2>&1` && [ -z "$x" ] && return 0 echo -n "Internal script error in: $p - $x Error eval in${2:+ in '$2'}. Press enter to skip & continue:" read x return 1 } _tee(){ local s="$1" i r=1 shift for i in "${@}"; do [ -e "$i" ] && echo "$s" >"$i" && r=0 done 2>/dev/null return $r } single(){ grep -qF ">$1<" "${PNP_TMP}.$2" && return 1 echo ">$1<" >>"${PNP_TMP}.$2" return 0 } gmsg(){ echo "> $*" } bmsg(){ echo "! $*" >&2 } mod(){ local m m1 m2 p= for m in "${@}"; do while [ -z "${m##*-*}" ]; do m="${m%%-*}_${m#*-}" done [ -e "/sys/module/$m" ] && continue # fast $CHK "$m" 0 || continue modalias "$m" || { echo ">$m<" >>"${PNP_TMP}".4 continue } case $PARALLEL in no|0) ;; 2) m2= for m1 in $ALIAS ; do modparam $m1 $INSMOD [ -e "$m1" ] && m2="$m2 insmod "$m1" $PARAM ;" || pnpass=1 done $cmd_quiet || echo -ne "\033[0G\033[0K$LCOUNT [...] $m1 $PARAM" eval "( ${m2%;} ) >/dev/null 2>&1 &" pids="$pids$! " continue ;; *) pids="$pids$pid " pid= ;; esac for m1 in $ALIAS ; do # m="${m1##*/}" # [ -e "/sys/module/${m%.ko}" ] && continue modparam $m1 $INSMOD [ -e "$m1" ] || { pnpass=1 continue } ${pid:+wait} $pid $cmd_quiet || echo -ne "\033[0G\033[0K$LCOUNT $m1 $PARAM" insmod "$m1" $PARAM >/dev/null 2>&1 & pid="$!" done done } mod_fast(){ # subst ${m//-/_} related to bb version mod(){ local m f= p= for m in "${@}"; do m=${m//-/_} [ -e "/sys/module/$m" ] && continue modalias "$m" || continue for m in $ALIAS ; do [ "$m" = "$f" ] && continue f="$m" m="${m##*/}" m="${m%.ko}" m=${m//-/_} [ -e "/sys/module/$m" ] && continue modparam $f $INSMOD [ -e "$f" ] || break $p $cmd_quiet || echo -ne "\033[0G\033[0K$LCOUNT $m $PARAM " insmod "$f" ${PARAM:+"$PARAM"} & p="wait $!" done done $p } } _wait(){ [ -n "$pid$pids" ] && { wait $pid $pids pid= pids= } } _re(){ local i=122 if [ "${i//2/3}" = 133 ]; then _re(){ echo "${1//$2/$3}";} else _re(){ echo "$1"|sed -e "s/$2/$3/g";} fi _re "${@}" } refresh(){ LCOUNT="${LCOUNT}." echo -ne "\033[0G\033[0K$LCOUNT" local i j l ${cmd_fast:=false} && { [ "$2" = r ] || return 1 [ -n "$save_REAL_ROOT" ] && REAL_ROOT="$save_REAL_ROOT" if [ -n "$REAL_ROOT" ]; then save_REAL_ROOT="$REAL_ROOT" [ -b "$REAL_ROOT" ] && return 1 [ -z "${REAL_ROOT##*=*}" ] && for i in $(part_ "$REAL_ROOT"); do [ -b "$i" ] && REAL_ROOT="$i" && cmd_detect_root=false && return 1 done elif [ -n "$DETECTED_ROOTS$DETECTED_LOOPS" ]; then return 1 fi [ "${cmd_fast_round:=3}" -le 0 ] && return 1 cmd_fast_round=$((cmd_fast_round-1)) echo "[$cmd_fast_round]" return 0 } _wait sed -e 's%^\([^ ]*\)[ ]*.*$%>\1<%g' "${PNP_TMP}".1 { cat -- `grep -ls '^DRIVER=' $($uFIND)`|grep "^DRIVER=\|^MODALIAS="|sed -e 's%-%_%g' -e 's%^.*=\(.*\)$%>\1<%g' >>"${PNP_TMP}".1;} "${PNP_TMP}".0 if grep -q "[/]sbin/mdev" /proc/*/cmdline; then REFRESH_SAME='' [ "$1" = n ] && REFRESH_SAME=1 return 0 fi [ "$REFRESH_SAME$1" = n ] || return 1 return 0 fi sort -u "${PNP_TMP}".1 >"${PNP_TMP}".0 if ! $cmd_quiet ; then echo -ne "\033[0G\033[0K${BOLD} ::${NORMAL}Loaded:" for i in $(sort -m ${PNP_TMP}.0 ${PNP_TMP}.3 | uniq -u) ; do [ "$1" = n ] && echo "$i" >>/nopnp.lst i="${i#>}" i="${i%<}" [ -e "/sys/module/$i" ] && echo -ne " $i" done echo '' elif $cmd_unload && [ "$1" = n ] ; then sort -m ${PNP_TMP}.0 ${PNP_TMP}.3 | uniq -u >>/nopnp.lst fi cat "${PNP_TMP}".1 $checks >"${PNP_TMP}".2 cp "${PNP_TMP}".0 "${PNP_TMP}".3 cat "${PNP_TMP}".4 >>"${PNP_TMP}".0 REFRESH_SAME= [ "$1" = n ] && REFRESH_SAME=1 return 0 } count(){ [ "${LCOUNT#????????????????}" = "${LCOUNT}" ] && return 0 bmsg "Deadloop?" return 1 } mnt_loop(){ local i if [ -b $1 ] && losetup $1 $2; then for i in 0 1 1 1 1 1; do mount -o ro,$cmd_loopflags $1 $3 2>/dev/null && return 0 sleep $i done mount -o ro,$cmd_loopflags $1 $3 && return 0 losetup -d $1 return 1 fi mount -o loop,ro,$cmd_loopflags $2 $3 } root_fsck_rw(){ # -w not working here # [ -w "$1" ] && return local b b="$(grep "^[^ ]* $1 .* ro," /proc/mounts)" || return b="${b%% *}" grep -q "^[^ ]* $1 .* rw," /proc/mounts && return echo "fsck+rw $b $1" /sbin/fsck -C0 -T -p "$b" case $? in 0|1)mount -o remount,rw "$1";; 2|3) sync echo fsck inspired reboot after 5 sec sleep 5 sync echo b >/proc/sysrq-trigger ;; esac } upcase(){ echo "$*"|tr a-z A-Z } part_(){ [ -b "$1" ] && echo "$*" && return ( blkid $1 || blkid -t "$1" ) | sed -e 's:^.* TYPE="swap".*$::g' -e 's/:.*$//g'|sort -u } # rootoverlay=/boot to overlay RW real_root zram_overlay(){ local dev ov=/overlay ov1="$NEW_ROOT/mnt/root-overlay" x1 x2 x3 next low=0 d b # first is upper/work RW dir, then going low while [ "$#" -gt 0 ]; do dev="${1#+}" [ "$dev" = "$1" ] && next=false || next=true [ "$dev" = true ] && dev= [ -z "$dev" ] && dev=/dev/zram0 echo -ne '(overlay)' [ $low = 0 ] && d="$ov" || d="$ov/low$low" mkdir -p $d case "$dev" in /dev/zram*) b="/sys/block/${dev#/dev/}" ln -s fsck /sbin/mkfs.ext4 echo "${2:-lz4hc}" >"$b"/comp_algorithm echo "${3:-8g}" >"$b"/disksize && mkfs.ext4 -q -O sparse_super2 -O ^has_journal -O ^inline_data -O dir_index -O ^project -O ^quota -E discard -E num_backup_sb=0 -b 4096 -I 128 "$dev" && mount -t ext4 -o noatime,discard,lazytime,noblock_validity,dioread_nolock,delalloc,nobarrier "$dev" $d || return 1 # always last choise shift shift shift ;; *) shift while read x1 x2 x3; do [ "$x1" = "$dev" -a -z "${x2##$NEW_ROOT/*}" ] && dev="${x2#$NEW_ROOT}" && break done /dev/null || mount --bind "$b" $d || continue fi ;; esac low=$((low+1)) $next || break done if [ "$low" != 0 ]; then local o mkdir -p $ov/up $ov/low $ov/work mount --move "$NEW_ROOT" $ov/low || continue while [ $low -gt 1 ]; do low=$((low-1)) o="$o:$ov/low$low" done mount -t overlay -o index=on,redirect_dir=on,upperdir=$ov/up,workdir=$ov/work,lowerdir=$ov/low$o,$cmd_rootoverlayflags none $NEW_ROOT && mkdir -p "$ov1" && mount --move $ov "$ov1" return $? fi return 1 } _hotplug(){ local h=/proc/sys/kernel/hotplug [ -e $h ] && ( [ "$SAVE_HOTPLUG" != - ] || read SAVE_HOTPLUG <$h ) && ( [ "$1" = - ] || echo "$1" >$h ) && return 0 _hotplug(){ return 1;} return 1 } mod_unload(){ local h i="$NEW_ROOT/lib/modules/$KV" l="$NEW_ROOT/usr/src/linux-$KV" m="" x y yy r=$NEW_ROOT/mnt/ram cd / _hotplug "$SAVE_HOTPLUG" ${cmd_fsck:-false} && if grep -q "^[^ ]* $NEW_ROOT squashfs" /proc/mounts; then root_fsck_rw "$NEW_ROOT/boot" else root_fsck_rw "$NEW_ROOT" fi [ "${cmd_rootoverlay:-false}" != false ] && zram_overlay $(_re "$cmd_rootoverlay" : ' ') if grep -q "^[^ ]* $NEW_ROOT squashfs" /proc/mounts; then echo -ne '(squashfs)' mkdir -p /etc/mnt cp -a $NEW_ROOT/mnt/* /etc/mnt mount -t ramfs none $NEW_ROOT/mnt -o rw,noatime,nodiratime && cp -a /etc/mnt/* $NEW_ROOT/mnt [ -e /etc/resolv.conf ] && { sort -u /etc/resolv.conf >$r/etc/resolv.conf h="${NFSROOT:-$REAL_ROOT}" x="${h##//}" x="${x%%[:/]*}" read y /dev/null y=`upcase "$y"` && sed -i \ -e "s:DC1\.DOMAIN\.LOCAL:$(upcase $x):g" \ -e "s:DOMAIN\.LOCAL:$y:g" \ -e "s:= DOMAIN:= ${y%%.*}:g" \ $r/etc/* $r/etc/*/* 2>/dev/null } } # /mnt/ram/ram.lst: [/] [] while read x y; do if [ -z "$y" ]; then mkdir -p $r${x%/*} cp -a $NEW_ROOT$x $r$x else mkdir -p $r$x chmod $y $r$x fi [ -n "${x##*/}" ] && mount --bind $r$x $NEW_ROOT$x done <$r/ram.lst fi if [ -L $i/kernel ] && i=`ls $l.*fs 2>/dev/null` && [ -f "$i" ]; then echo -ne "(mount $i)" mnt_loop /dev/loop3 "$i" $l elif ! [ -e $i ] ; then if ${cmd_autoinstall:-false} ; then echo -ne "(Installing /lib/modules/$KV)" mount -o remount,rw ${NEW_ROOT} && cp -a /lib/modules/$KV $i else echo -ne '(use "autoinstall" to install modules)' fi fi # for i in /rd /lib; do # [ -d "$i" ] && umount $i && break # done umount /lib/modules /lib/firmware /rd /lib 2>/dev/null losetup -d /dev/loop1 >/dev/null 2>&1 l= $cmd_unload && [ -n "$REAL_ROOT" ] && [ -e "/nopnp.lst" ] || return echo -n "(removing unlocked modules" while read i; do i="${i#>}" l="${i%<} $l" done /dev/null 2>&1 i="$(cat /proc/modules)" done echo -n ')' } early_huge(){ local d=/sys/kernel/mm/transparent_hugepage [ "$cmd_transparent_hugepage_misc" = true -a -d $d ] || return case "`cat $d/enabled`" in *\[never\]*)return;; esac echo defer+madvise >$d/defrag 2>/dev/null||echo defer >$d/defrag||return echo always >$d/shmem_enabled } pnp_options(){ eval "set -- `cat /proc/cmdline` `[ -e /cmdline ]&&cat /cmdline`" pnp_options(){ return;} PARALLEL=0 cmd_nofb=false cmd_nopnp=false cmd_unload=false cmd_noraid=false cmd_real_init=/sbin/init local i v m p= d="$TMPDIR/modparam" x=';; ' mkdir $d for i in "${@}" ; do case "$i" in parallel-startup) PARALLEL=1 ;; parallel-startup=*) PARALLEL="${i#*=}" ;; moduleparam=*) i="${i#*=}" p="*/${i%%:*}.ko)PARAM=\"${i#*:}\"$x$p" ;; md=*) v="cmd_${i%%=*}" eval "$v=\"\$$v ${i#*=}\"" ;; *=*) v="${i%%=*}" case "$v" in *.*) echo "${i#*.}" >"$d/${v%%/*}";; *) export cmd_`echo "$v"|sed -e 's:[^a-zA-Z0-9_]:_:g'`="${i#*=}" ;; esac ;; *.*) echo "${i#*.}" >"$d/${i%%/*}";; scandelay) cmd_scandelay=10 ;; *) export cmd_`echo "$i"|sed -e 's:[^a-zA-Z0-9_]:_:g'`=true ;; esac done v= for i in $(ls -1 "$d"); do m="${i%%.*}" [ -n "$m" ] && i="$(cat "$d/$i")" || continue [ "x$i" = 'x!' ] && cmd_noload="$cmd_noload,$m" && continue [ -z "$i" ] && MDOLIST="$MDOLIST $m" [ "$v" = "$m" ] && { p="$p $i" continue } [ -n "$v" ] && p="$p'$x" p="$p*/$m.ko)PARAM='$i" v="$m" done [ -n "$v" ] && p="$p'$x" # rm "$d" -Rf $cmd_nofb && p="*/fb.ko|*/drm_kms_helper.ko)INSMOD=continue$x$p" [ -n "$cmd_noload" ] && p="*/$(_re "${cmd_noload#,}" , '.ko|*/').ko)INSMOD=continue$x$p" p="modparam(){ INSMOD= case \"\$1\" in 1)INSMOD=\${REORDER:-continue};; $p *)PARAM='';; esac }" etest "$p" 'modparam.sh' && echo "$p" >/etc/modparam.sh $cmd_quiet && good_msg(){ return; } && gmsg(){ return; } } link_dir(){ local i for i in "$1"/*; do i="${i#$1}" if [ -L "$1$i" ] && ( [ -L "$2$i" ] || ! [ -e "$2$i" ] ) ; then cp "$1$i" "$2$i" -a elif [ -d "$2$i" ]; then if [ -L "$2$i" ]; then local d="$(readlink "$2$i")" rm "$2$i" mkdir "$2$i" link_dir "$d" "$2$i" fi link_dir "$1$i" "$2$i" # bb 1.33.0 BUG! #elif [ "$i" != "/*" ]; then elif [ "$i" != '/*' ]; then ln -sf "$1$i" "$2$i" fi done } pnp_init(){ local l pnp_options $cmd_fast && mod_fast _hotplug - for l in /*.loopfs; do if [ -f "$l" ]; then for i in `find /lib -name "*.ko"` ; do insmod $i done local d="${l%.loopfs}" mkdir $d 2>/dev/null mnt_loop /dev/loop1 $l $d break fi done [ -d /rd ] && link_dir /rd [ -d /lib/root ] && link_dir /lib/root [ -e /lib/modules/$KV/modules.dep ] && return # pnponly rm /sbin/modprobe } # postprocess embedded module params. load zswap modules, etc post_modparam(){ local i p v v0 v1 n for i in "$TMPDIR/modparam"/*.*; do p="${i##*/}" n="${p#*.}" p="/sys/module/${p%%.*}/parameters/$n" [ -e "$p" ] && read v <"$i" && v1="${v#$n=}" && [ "$v" != "$v1" ] && read v0 <"$p" && [ "$v0" != "$v1" -a "$v0:$v1" != Y:1 -a "$v0:$v1" != N:0 ] && echo "$v1" >"$p" done } override_modprobe(){ loadsh modprobe || return local f=/sbin/modprobe [ -e $f ] && ! ( grep -q "bug #197730" $f && rm $f ) && return ln -s /etc/modprobe.sh $f echo $f >/proc/sys/kernel/modprobe } wild(){ grep -e "$1" /dev/null 2>&1 mod $i c="$i" _wait for i in `grep -lse "$c" $(find /sys/devices/system/cpu -name scaling_driver)` ; do read i2 <"${i%scaling_driver}cpuinfo_transition_latency" || continue [ "$i2" -gt "${l:=${i2}}" ] && continue if [ "$i2" = "$l" ] ; then [ "${freq#*${c} }" = "$freq" ] && freq="$freq$c " else freq=" $c " l="$i2" fi ok="$c" break done 2>/dev/null /dev/null 2>&1 [ "$freq" != "$c" ] && mod $freq } cpufreq_gov(){ local gov1= for i1 in $gov ; do mod cpufreq_${i1} _wait for i in `find /sys/devices/system/cpu -name scaling_governor` ; do echo $i1 >"$i" || gov1="$gov1 $i1" # [ "$(cat "$i")" = "$i1" ] || gov1="$gov1 $i" done 2>/dev/null rmmod cpufreq_${i1} >/dev/null 2>&1 [ -z "$gov1" ] && break done } empty_hwopts(){ local i [ -e /etc/modules ] && for i in $* ; do echo -ne '' >/etc/modules/$i done } # params: part loop net? # out: $DETECTED_LOOPS++, $DETECTED_ROOTS++ detect_part(){ grep -qF ">$*<" "${PNP_TMP}.5" && return 0 local l o=ro,$cmd_real_rootflags _wait $cmd_quiet || echo -ne "\033[0G\033[0K$LCOUNT Inspecting: $1" mkdir /DETECT_ROOT || return 1 [ -n "$3" ] && { o="$o,nolock,rsize=1024,wsize=1024" case "$3:$1" in cifs:*|auto://*)o="$o,user=,guest -t cifs";; auto:*|nfs:*)o="$o -t nfs";; *)o="$o,user=,guest -t $3";; esac } mount -o $o "$1" /DETECT_ROOT >/dev/null 2>&1 || { rmdir /DETECT_ROOT return 1 } echo ">$*<" >>"${PNP_TMP}.5" [ "${2:-false}" != false ] && for l in $( { if [ "$2" = true ]; then fstype ${LOOPS_} else fstype /DETECT_ROOT/$2 fi } |sed -e 's%^\(.*:\).* TYPE="\([^"]*\)".*$%\1\2%g' ) ; do DETECTED_LOOPS="$DETECTED_LOOPS $1:${l#/DETECT_ROOT/}" l="${l#*:}" case "$l" in ext2) LOOPTYPE=normal ;; *) LOOPTYPE="$l" ;; esac mod $l # loop done [ -e "/DETECT_ROOT/$cmd_real_init" ] && grep -sq "^$1[ ]*/[ ]" /DETECT_ROOT/etc/mtab && DETECTED_ROOTS="$DETECTED_ROOTS $1" # [ -e "/DETECT_ROOT/$cmd_real_init" ] && DETECTED_ROOTS="$DETECTED_ROOTS $1" umount /DETECT_ROOT >/dev/null 2>&1 rmdir /DETECT_ROOT } detect_root(){ local i d="${cmd_detect_root:-false}" l="$cmd_loop" fs [ "$d" = true ] && d= if [ "$d" != false ]; then # if real_root & loop hard-defined - don't probe other loops [ -n "$REAL_ROOT" ] && [ "${l:-true}" != true ] && l=false # if real_root & loop hard-defined - probe all loops # [ -n "$REAL_ROOT" ] && [ "${l:-true}" != true ] && l=true for i in `part_ "$d"`; do case "$i" in /dev/loop1) ;; *) detect_part "$i" "$l" ;; esac done fi if [ -n "$REAL_ROOT" ] && [ "${cmd_loop:-false}" != false ]; then detect_part "$(part_ "$REAL_ROOT")" "$cmd_loop" fi [ -n "$NFSROOT" ] && [ -n "`ifconfig`" ] && { detect_part "$NFSROOT" "$cmd_loop" "${NFSLIKE_FS:-auto}" } [ "$d" = false -a -n "$REAL_ROOT" -a ! -b "$REAL_ROOT" ] && for i in `part_ "$REAL_ROOT"`; do [ -b "$i" ] && REAL_ROOT="$i" && break done } _ifaces(){ local i for i in /sys/class/net/*; do i=${i##*/} case "$i" in lo|nlmon);; *)echo "$i";; esac done } # autoconfig works only with built-in card? ip_config(){ local ip dev s d h [ -n "`ifconfig`" ] && { [ -z "$NFSROOT" ] && { NFSROOT="$(dhcp_get rootserver):$(dhcp_get rootpath)" [ "$NFSROOT" = : ] && NFSROOT= } return } for ip in "${@}"; do msg_ "Configuring IP $ip" case "$1" in # forever everywere +) for i in $(_ifaces); do udhcpc -i $i -V genpnprd -f -A 5 >/dev/null 2>&1 & done return ;; # to success round-robin \*) while true; do for i in $(_ifaces); do udhcpc -i $i -V genpnprd -vnq -t 1 -T 1 && return done done ;; esac eval "set -- $(_re "'$ip'" : "' '") ''" for dev in ${6:-$(_ifaces)}; do d= case "$7" in on|any|dhcp) mod af_packet msg_ busybox udhcpc -i $dev -V genpnprd -n -T 15 -q || continue d=`grep -s '^domain ' /etc/resolv.conf` && d="${d#domain }" [ -e /rootpath ] && NFSROOT=`cat /rootpath` ;; esac [ -n "$1$4" ] && if [ -z "$4" ]; then ip addr add dev $dev $1 brd + || continue ip link set $dev up else ifconfig $dev $1 netmask $4 up || continue fi i="${5%%.*}" [ -n "$i" ] && echo "$i" >/proc/sys/kernel/hostname [ "$i" != "$5" ] && d="${5#*.}" [ -n "$d" ] && for d in $d; do echo "search $d" >>/etc/resolv.conf echo "$d" >/proc/sys/kernel/domainname done [ -n "$3" ] && route add default gw $3 dev $dev case "$NFSLIKE_FS" in cifs)i="//$2/";; *)i="$2:";; esac NFSROOT="${2:+$s}$cmd_nfsroot" break done done [ ${cmd_telnetd:-false} != false ] && [ -n "`ifconfig`" ] && telnetd ${cmd_telnetd#true} } dhcp_get(){ local i r='' for i in `busybox dmesg | grep rootserver | sed -e 's/,/ /g'`; do if [ "`_re "$i" = ' '|cut -d ' ' -f 1`" = "$1" ]; then r="`_re "$i" = ' '| cut -d ' ' -f 2`" # FIXME: first value will be more balanced, but last - actual in longrun break fi done echo -ne "$r" } # modifyed genkernel's function to support other network filesystems (/dev/) findnfsmount() { ( [ -z "$NFSLIKE_FS" ] && [ -n "$NFSROOT" ] ) || grep -q "[ ]${NFSLIKE_FS:=nfs}\$" /proc/filesystems || return 1 ip_config ::::::dhcp if [ -n "`ifconfig`" ]; then if [ -z "$NFSROOT" ]; then bmsg "The DHCP Server did not send a valid root-path." bmsg "Please check your DHCP setup, or provide a nfsroot=<...> parameter." else local o="ro,nolock,rsize=1024,wsize=1024,$cmd_real_rootflags" m="$NEW_ROOT" unc [ "$CDROOT" != 0 ] && m="$m/mnt/cdrom" case "$NFSLIKE_FS:$NFSROOT" in cifs:*|://*)o="$o,user=,guest,serverino";NFSLIKE_FS=cifs;; :*|nfs:*)NFSLIKE_FS=nfs;; *)o="$o,user=,guest $o,user= $o";; esac grep -q "[ ]${NFSLIKE_FS:=nfs}\$" /proc/filesystems || return 1 for o in $o; do for unc in '' "$(echo ",unc=$NFSROOT"|sed -e 's:/:\\:g')"; do # try new cifs gmsg "Attempting to mount $NFSLIKE_FS on $NFSROOT into $m -o $o" if mount -t $NFSLIKE_FS "$NFSROOT" $m -o "$o$unc" ; then # FIXME: Need to start portmap and the other rpc daemons in # order to remount rw. REAL_ROOT=/dev/nfs REAL_ROOTFLAGS="$o" return 0 fi [ "$NFSLIKE_FS" = nfs ] && break done done bmsg "$NFSLIKE_FS Mounting failed. Is the path correct ?" fi fi return 1 } msg_(){ _wait if $cmd_quiet; then echo -ne "\033[0G" else echo -ne "\033[0G\033[0K" [ -n "$*" ] && gmsg "$*" fi } fstype(){ { blkid "${@}" || blkid -t "${@}" || echo "${@}";} 2>/dev/null } resume(){ local i [ -e /sys/power/resume ] || return [ -n "$*" ] && for i in "${@}"; do [ "$i" = true ] && { cat -- $(grep -l "[1-9]" /sys/class/block/*/size|grep -v /loop|sed -e 's:size$:dev:') >/sys/power/resume continue } i="${i#/dev/}" for i in "/sys/class/block/$i/" `grep -ls "^DEVNAME=$i$" /sys/class/block/*/uevent`; do cat -- "${i%uevent}dev" >/sys/power/resume done done 2>/dev/null /sys/power/resume 2>/dev/null } mdadm(){ echo " # mdadm $*" >&2 /sbin/mdadm "${@}" } _wait4(){ [ -e "$1" ] && return 0 local i=${GK_UDEV_TIMEOUT:-120} echo -n "WAIT for $1 $i.." >&2 sleep .1 while [ "$i" -gt 0 -a ! -e "$1" ]; do sleep 1 i=$((i-1)) done echo "$i" >&2 [ -e "$1" ] } _settle1(){ local i for i in /sys/class/block/*; do i="/dev/${i##*/}" [ -e "$i" -o "$i" = '/dev/*' ] || { "${@}" _wait4 "$i" || return 1 } done return 0 } _settle(){ [ -e /sbin/udevadm ] && udevadm settle --timeout=${cmd_udev_timeout:-${GK_UDEV_TIMEOUT:-120}} || _settle1 } _udevd(){ [ "$cmd_noudev" != true -a -e /sbin/udevd ] || return 1 _hotplug '' [ -f /etc/udev/hwdb.bin ] || udevadm hwdb --update udevd --resolve-names=never --daemon || return 1 udevadm trigger --action=add _settle return 0 } _waitscan(){ $waitscan || return waitscan=false $cmd_fast && [ -b "$REAL_ROOT" ] || { local i= sm=/sys/module/scsi_mod/parameters sms= [ -e /etc/modules/waitscan ] || { for i in scsi_wait_scan scsi_mod; do [ -e "/lib/modules/$KV/kernel/drivers/scsi/$i.ko" ] && { mod $i break } done } empty_hwopts waitscan [ -n "$cmd_scandelay" ] && sleep "$cmd_scandelay" _wait [ "$i" = scsi_wait_scan ] && rmmod $i 2>/dev/null _settle } [ -n "$cmd_elevator" ] && _tee "$cmd_elevator" /sys/class/block/*/queue/scheduler # embed } detect_fs(){ local i= m= md="$USE_MDADM" dm="$USE_DMRAID_NORMAL" t="$cmd_detect_root" lvm="$USE_LVM_NORMAL" evms="$USE_EVMS_NORMAL" mddef=true [ -n "$NFSLIKE_FS" ] && [ "$REAL_ROOT" = /dev/nfs ] && REAL_ROOT="/dev/$NFSLIKE_FS" case "$t" in true|false)t='';; esac _waitscan resume "$cmd_resume" # dmraid/lvm/evms unsure for i in $( { fstype $t [ -n "$REAL_ROOT" ] && ( [ -n "$t" ] || ! [ -b "$REAL_ROOT" ] ) && [ "$REAL_ROOT" != "$t" ] && fstype $REAL_ROOT } 2>/dev/null | sed -e 's%^\(/dev/[^ ]*\):.* TYPE="swsuspend".*$%0susp:\1%' -e 's:^.* TYPE="\([^"]*\)".*$:\1:g'| sort -u ); do case $i in /dev/md*) [ -x /sbin/mdadm ] || mknod "$i" b 9 "${i#/dev/md}" md=1 ;; linux_raid_member|mdraid) md=1 ;; # use right blkid /dev/mapper*|/dev/dm*) dm=1 ;; EVMS*|evms*) evms=1 dm=1 ;; LVM*|lvm*) lvm=1 dm=1 ;; *raid*) m="$m $(wild "/$i/\|raid") $i" dm=1 ;; /dev/*) continue # think again [ "$REAL_ROOT" = "$i" ] && REAL_ROOT=/dev/nfs # compat i="${i#/dev/}" m="$m $i" NFSLIKE_FS="$i" ;; swap) ;; 0susp:*)[ -z "$cmd_resume" ] && resume "${i#0susp:}";; *) m="$m $(wild "/$i/") $i" ;; esac done [ -n "$dm" ] && m="$m dm-mod" # FIXME: IMHO it will be loaded after dmraid failure # [ -n "$dm" ] && m=$m $(wild "/md/dm-\|raid_class")" mod $(for i in $m;do echo "$i";done|sort -u) if [ -n "$evms" ]; then msg_ "Activating EVMS" if evms_activate ; then USE_EVMS_NORMAL_= lvm= USE_LVM_NORMAL= USE_LVM_NORMAL_= fi fi if [ -n "$lvm" ]; then msg_ "Activating LVM" if vgscan --ignorelockingfailure --mknodes; then sleep 2 vgchange -ay --ignorelockingfailure USE_LVM_NORMAL_= evms= USE_EVMS_NORMAL= USE_EVMS_NORMAL_= fi 2>/dev/null fi for i in $cmd_md ; do set -- `_re "$i" , ' '` "" i="$1$2$3$4" if [ -n "$5" ] && [ "${i##*/dev/}" = "$i" ]; then mod "raid$2" i="$1 --level=$2 --chunk=$3" shift 4 i="--build /dev/md$i" else mod $(wild "/md/raid") i="$1" shift [ "${i#d}" != "$i" ] && i="${i#d} --run" i="--assemble /dev/md$i" fi msg_ mdadm $i --raid-devices=$# $* done if [ -n "$md$dm" ]; then # maybe dm wrong here, but try if [ -e '/etc/mdadm.conf' ]; then mod `( grep ' level=' /etc/mdadm.conf || ( mdadm --examine --scan -v|grep ' level=' ) ) | sed -e 's:^.* level=\([^ ]*\) .*$:\1:g' | sort -u` else mddef=false [ -n "$t" ] && echo "DEVICE $t" >/etc/mdadm.conf # filter all extra info around bug with journal=spares mdadm --examine --scan|grep '^ARRAY' >/etc/mdadm.conf.all mod `grep ' level=' /etc/mdadm.conf.all | sed -e 's:^.* level=\([^ ]*\) .*$:\1:g' | sort -u` if [ "$cmd_detect_root" != true ] && [ -n "$USE_MDADM" ]; then # do not assemble other raids while read i; do [ "${i#ARRAY $REAL_ROOT }" = "$i" -a "${i#ARRAY $cmd_detect_root }" = "$i" ] || echo "$i" done /etc/mdadm.conf fi [ -s /etc/mdadm.conf ] || cp /etc/mdadm.conf.all /etc/mdadm.conf fi if ! $cmd_noraid && ( [ -n "$md" ] || grep -q ARRAY /etc/mdadm.conf ); then msg_ case "$cmd_domdadm" in async) mod $(wild /md/) mdadm --assemble --scan & USE_MDADM_= sleep 5 ;; ?*) [ "$cmd_domdadm" = true ] && cmd_domdadm=--scan mdadm --assemble $cmd_domdadm || ( mod $(wild /md/) ; ( mdadm --assemble $cmd_domdadm || ( [ -n "$cmd_part$REAL_ROOT" ] && mdstart $cmd_part $REAL_ROOT ) || raidautorun $REAL_ROOT ) ) && USE_MDADM_= ;; *)mdadm --assemble $REAL_ROOT && USE_MDADM_='';; esac fi $mddef || rm /etc/mdadm.conf fi if [ -n "$dm" ]; then mod $(dmraid -r --sep " " -cf,r,t $t 2>/dev/null) if ! $cmd_noraid; then msg_ 'Activating Device-Mapper RAID(s)' dmraid -ay ${DMRAID_OPTS} || { mod $(wild "/md/\|raid") msg_ dmraid -ay ${DMRAID_OPTS} } && USE_DMRAID_NORMAL_= fi fi case "$cmd_dobtrfs" in true)btrfs device scan;; ?*)btrfs device scan $cmd_dobtrfs;; esac _settle resume "$cmd_resume" detect_root return 0 } tryopt(){ [ -n "$DETECTED_ROOTS$DETECTED_LOOPS" ] && return 1 [ -n "$REAL_ROOT" -a -e "$REAL_ROOT" ] && return 1 local x sm=/sys/module/scsi_mod/parameters smf= sms= ok=false while TRYOPT=$((TRYOPT+1)); do case "$TRYOPT" in 1|3|4|5|6) read sms <$sm/scan && [ "$sms" = async ] && echo sync >$sm/scan [ "$TRYOPT" -lt 4 -o "$TRYOPT" = 6 ] && _tee '- - -' /sys/class/scsi_host/host*/scan && ok=true && bmsg 'SCSI rescan' [ "$TRYOPT" -gt 3 ] && tee 1 $(find /sys -name rescan) && ok=true && bmsg 'devices rescan' [ "$sms" = async ] && echo async >$sm/scan $ok && waitscan=true && return 0 ;; 2)read smf <$sm/default_dev_flags && x=$((smf|0x240)) && [ "$smf" != "$x" ] && x=$((smf|0x240)) && [ "$smf" = 0 ] && echo 0x240 >$sm/default_dev_flags && waitscan=true && bmsg "try scsi_mod.default_dev_flags=$x ($smf | 0x240)" && return 0;; *)return 1;; esac done return 1 } gentoo_compat_hwopts(){ local i i1 for i1 in ${MY_HWOPTS} ; do i="/etc/modules/$i1" if [ -e "$i" ]; then for i in `cat "$i"` ; do grep -q "^$i\$" "modules.pnp" || mod "$i" done else mod $(wild "/${i1}[./]") fi done } load_hand_made(){ ## some hand-made autoloads # $cmd_nofb || [ -z "$(cat /proc/fb 2>/dev/null)" ] || mod fbcon mod $(cd /etc/modflags && cat -- $(ls -1 /sys/module) /dev/null) grep -sq yeah /proc/sys/net/ipv4/tcp_available_congestion_control && echo yeah >/proc/sys/net/ipv4/tcp_congestion_control [ -e /dev/freefall ] && [ -x /bin/hpfall ] && /bin/hpfall /dev/sda } load_hand_made0(){ ## some hand-made autoloads, stage0 local f=`echo $(grep "^vendor_id\|^flags" /proc/cpuinfo|sort -u)` mod $MDOLIST ${cmd_elevator:+${cmd_elevator}_iosched} $(cd /etc/modflags && cat -- $(cat /sys/bus/acpi/devices/*/path|sed -e 's:^\\::') $f $(ls -1 /sys/module) /dev/null) _wait # frost. save your silicon (and power): autoload best cpufreq driver freq=`cat -- $(find /sys/devices/system/cpu -name scaling_driver 2>/dev/null) /sys/devices/system/cpu/amd_pstate/status cpufreq powernow-k8 : ${gov:=_schedutil conservative ondemand} ;; *AuthenticAMD*) cpufreq cpufreq-nforce2 cpufreq powernow ;; # UltraSPARC-IIe)return;; # ondemand & conservative kill him UltraSPARC*)return;; esac local i=/sys/devices/system/cpu/intel_pstate/status if [ -e $i ]; then [ -z "$cmd_intel_pstate" ] && echo active >$i 2>/dev/null else cpufreq cpufreq "drivers/cpufreq/\|powernow\|nforce2" fi [ -z "$freq" ] && return ${cmd_nopowersave:-false} && return if grep -vsq "schedutil\|powersave\|userspace\|conservative\|ondemand\|performance" /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; then gov= elif [ -z "$gov" ]; then $onbatt && gov='conservative _schedutil ondemand powersave' || gov='ondemand conservative performance' fi cpufreq_gov rmmod freq_table >/dev/null 2>&1 if $onbatt; then _tee min_power /sys/class/scsi_host/*/link_power_management_policy _tee 1 /sys/devices/system/cpu/cpufreq/*/ignore_nice_load /sys/module/*/parameters/power_save _tee 2 /sys/devices/system/cpu/sched_*_power_savings fi } load_misc(){ # do: loadall[=...] or process MY_HWOPTS for i in $cmd_loadall ; do [ "$i" = true ] && i= i1="${i%%:*}" i2="${i#*:}" [ -z "$i1" ] && i1='.*' # default: exclude slow probe, fatal to unload, etc [ "$i2" = "$i" ] && i2='/tcrypt.ko\|/paride/\|/media/\|/sound/\|/microcode\.\|/isdn/\|/net/\|/video/' mod $(wild "$i1" "$i2") done [ -z "$cmd_loadall" ] && [ "$NODETECT" != 1 ] && gentoo_compat_hwopts # deprecated ip_config $cmd_ip detect_fs } set_root_loop(){ set -- 1 `_re "$1" : ' '` REAL_ROOT="$2" LOOP="$3" LOOPTYPE="$4" } # vs. "find" optimization [dis]order ordered_modalias(){ local i if [ -e "$1/modalias" ]; then ! grep -sq '^DRIVER=.' "$1/uevent" && mod "`cat -- "$1/modalias"`" # elif [ -e "$1/uevent" ]; then # i=`grep -s '^MODALIAS=' "$1/uevent"` && mod "${i#MODALIAS=}" fi for i in "$1"/* ; do [ -d "$i" ] && [ ! -L "$i" ] && ordered_modalias "$i" done } fast_modalias(){ # ssb (b43) have no modalias mod $MDOLIST `grep -sh '^MODALIAS=' $($uFIND) /dev/null ; then if [ -z "$NFSLIKE_FS" ] || ! findnfsmount; then mount -t "${cmd_rootfstype:-auto}" -o ro,$cmd_real_rootflags "$REAL_ROOT" "$NEW_ROOT" || rmdir "$NEW_ROOT" fi [ "$NEW_ROOT" = /dev/nfs ] && [ -e /newroot ] && NEW_ROOT="/newroot" if [ -e "$NEW_ROOT" ] && [ -n "$LOOP" ]; then LOOP_ROOT= # LOOP_ROOT="$NEW_ROOT" for i in mnt/livecd; do [ -d $NEW_ROOT/$i ] && LOOP_ROOT="$NEW_ROOT/$i" && break done [ -z "$LOOP_ROOT" ] && mkdir ${LOOP_ROOT:=/newroot.loop} if ! ( [ -d "$LOOP_ROOT" ] && mnt_loop /dev/loop0 "/newroot/$LOOP" "$LOOP_ROOT" && [ -e "$LOOP_ROOT$cmd_real_init" ] ) ; then umount "$LOOP_ROOT" losetup -d /dev/loop0 rmdir "$LOOP_ROOT" umount "$NEW_ROOT" rmdir "$NEW_ROOT" LOOP_ROOT= fi if [ "$LOOP_ROOT" != "$NEW_ROOT" ] && [ -n "${LOOP_ROOT##$NEW_ROOT/*}" ] && [ -e "$LOOP_ROOT" ] && mount --move $NEW_ROOT $LOOP_ROOT/boot; then mount --move $LOOP_ROOT $NEW_ROOT rmdir $LOOP_ROOT && LOOP_ROOT="$NEW_ROOT" fi fi cp /proc/mounts /etc/mtab # around genkernel [ -d "$NEW_ROOT" ] && { REAL_ROOTFLAGS="$REAL_ROOTFLAGS,remount" if grep -q "^/dev/loop0 $NEW_ROOT " /proc/mounts; then LOOP= LOOPTYPE= REAL_ROOT=/dev/loop0 REAL_ROOTFLAGS=loop,remount,ro fi } fi } syspnp(){ [ -e "/lib/modules/$KV/kernel" -a ! -e "/lib/modules/$KV/modules.alias.sh" ] && return $cmd_nopnp && return early_huge # +some compats local PNP_TMP="${TMPDIR}/pnp.found" NOTLOADED="" CHK=single i i1 i2 gov= freq= pid= LCOUNT= REORDER=break USE_MDADM_="${USE_MDADM:=$cmd_domdadm}" USE_DMRAID_NORMAL_="${USE_DMRAID_NORMAL:=$cmd_dodmraid}" USE_EVMS_NORMAL_="${USE_EVMS_NORMAL:=$cmd_doevms}" USE_LVM_NORMAL_="${USE_LVM_NORMAL:=$cmd_dolvm}" LOOPS_= REFRESH_SAME waitscan=true checks= [ "${USE_DMRAID_NORMAL:-true}" = true ] || DMRAID_OPTS="$USE_DMRAID_NORMAL" : ${REAL_ROOT:=$cmd_real_root} : ${LOOP:=$cmd_loop} : ${LOOPTYPE:=$cmd_loop_type} : ${NFSROOT:=$cmd_nfsroot} for i in ${LOOPS:-"/*"}; do LOOPS_="${LOOPS_} /DETECT_ROOT$i" done [ ${cmd_passwd:-false} != false ] && [ -n /etc/passwd ] && echo "$cmd_passwd" >/etc/passwd /sbin/onbatt && onbatt=true || onbatt=false gmsg 'Searching pnp' override_modprobe [ "${SHLOADED##* modprobe }" = "${SHLOADED}" ] && mod(){ modprobe -q -a "${@}";} loadsh blkid empty_hwopts firewire net pata pcmcia sata scsi usb ataraid dmraid evms lvm mdadm fs [ -z "$ISCSI_INITIATORNAME$ISCSI_TARGET$ISCSI_ADDRESS" ] && empty_hwopts iscsi post_modparam $cmd_fast && [ ! -e "/lib/modules/$KV/modules.alias.sh" ] || for pnpass in 0 0; do for i in 0 1 2 3 4 5; do echo -ne '' >"${PNP_TMP}.$i" done REORDER=break REFRESH_SAME= CHK=true etc_modalias refresh n load_hand_made0 # first pass - strict bus order if $cmd_fast; then ofast_modalias || ordered_modalias $SYS_FIND else CHK=single fi etc_modalias # refresh # paranoid while refresh && count ; do fast_modalias done REFRESH_SAME=1 checks="$checks /proc/partitions" while count ; do if [ -n "$REORDER" ]; then REORDER= load_hand_made _wait else $cmd_fast || fast_modalias fi etc_modalias $cmd_unload && refresh load_misc etc_modalias && ln -s /proc /etc/modalias 2>/dev/null refresh n r || tryopt || break done [ $pnpass != 1 ] && break mntnewroot mount --bind $NEW_ROOT/lib/modules /lib/modules || break mount --bind $NEW_ROOT/lib/firmware /lib/firmware gmsg 'Thin boot, pass 2' done MY_HWOPTS= MDOLIST= USE_MDADM="${USE_MDADM_}" USE_DMRAID_NORMAL="${USE_DMRAID_NORMAL_}" USE_LVM_NORMAL="${USE_LVM_NORMAL_}" USE_EVMS_NORMAL="${USE_EVMS_NORMAL_}" # echo -ne "\033[0G\033[0K" j=0 for i in /sys/module/*; do j=$((j+1)) done echo "$j modules" # assign detected root/loop if [ -z "$REAL_ROOT" ]; then DETECTED_ROOTS="${DETECTED_ROOTS# }" DETECTED_LOOPS="${DETECTED_LOOPS# }" [ "${DETECTED_ROOTS#* }" = "$DETECTED_ROOTS" ] && DETECTED_ROOT="$DETECTED_ROOTS" [ "${DETECTED_LOOPS#* }" = "$DETECTED_LOOPS" ] && DETECTED_LOOP="$DETECTED_LOOPS" [ "${cmd_loop:-true}" = true ] && REAL_ROOT="$DETECTED_ROOT" ( [ "$cmd_loop" != true ] || [ -z "$DETECTED_ROOTS" ] ) && [ -z "$REAL_ROOT" ] && set_root_loop "$DETECTED_LOOP" if [ -z "$REAL_ROOT" ]; then [ -n "$DETECTED_ROOTS" ] && bmsg "Detected possible root devices: $DETECTED_ROOTS" [ -n "$DETECTED_LOOPS" ] && bmsg "Detected loopbacks: $DETECTED_LOOPS" fi fi # genkernel [ "$1" != true -a -n "$REAL_ROOT" ] && { [ -n "$GK_ROOTFS_DETECTED_STATEFILE" -a -b "$REAL_ROOT" -a "$cmd_fast" = true ] && echo "$REAL_ROOT" >$GK_ROOTFS_DETECTED_STATEFILE [ -n "$LOOP" ] && mntnewroot } gmsg "Boot time: $(cat /proc/uptime)" if [ -n "${NOTLOADED}" ] ; then gmsg "Not loaded:$NOTLOADED" # try again MDOLIST="$NOTLOADED" fi rm "${PNP_TMP}".? -f # cd / } vkb(){ # if [ -n "$cmd_vkb_touchscreen" ] || grep "^B: ABS=........" /proc/bus/input/devices ; then if [ -n "$cmd_vkb_touchscreen" ]; then # to debug /sbin/vkb elif [ "$1" = 1 -o -z "$SHELL" ]; then local i read i echo "$i" else $SHELL fi } run_dropbear(){ [ -e /usr/sbin/dropbear ] || return mkdir -P /var/run [ -z "$cmd_ip" ] && ip_config + /usr/sbin/dropbear -R "${@}" [ -z "$cmd_ip" -a "$1" != -FE ] && killall udhcpc && sleep 3 } run_shell(){ case "$cmd_dosshd" in shell)run_dropbear -FE;return;; +)run_dropbear;; esac [ -z "$SHELL" ] && for SHELL in /bin/ash /bin/bash /bin/sh; do [ -e "$SHELL" ] && break done export SHELL vkb [ -e /var/run/dropbear.pid ] && { killall dropbear [ -z "$cmd_ip" ] && killall udhcpc sleep 3 } } _initnext(){ mod_unload mount --move /dev "$NEW_ROOT"/dev umount /proc /sys exec "${@}" } # minimalistic. debug if [ -z "$KV" ] && ! [ -e /proc/version ]; then NEW_ROOT="/newroot" CDROOT=0 mount -t proc proc /proc /bin/busybox --install -s mount -t sysfs sys /sys mount -t devtmpfs -o exec,nosuid,mode=0755,size=10M dev /dev && devfs=true || devfs=false pnp_options cd /sys read KV /dev/null override_modprobe syspnp true cd / [ "$cmd_dosshd" = true ] && run_dropbear -FE while true; do [ -n "$REAL_ROOT" ] && mntnewroot if [ -n "$LOOP_ROOT" ] && [ -d "$LOOP_ROOT" ] && [ "$LOOP_ROOT" != "$NEW_ROOT" ]; then mkdir /rd 2>/dev/null ( mnt_loop /dev/loop1 /lib.loopfs /rd && link_dir /rd /lib ) || ( mnt_loop /dev/loop1 /rd.loopfs /rd && link_dir /rd ) link_dir "$LOOP_ROOT" _initnext "$cmd_real_init" $cmd_init_opts elif [ -d "$NEW_ROOT" ]; then _initnext /sbin/switch_root -c /dev/console "$NEW_ROOT" "$cmd_real_init" $cmd_init_opts else bmsg 'failed to mount root' while true; do cat /lib/keymaps/keymapList echo -n 'Enter root partition, keymap or "shell":' REAL_ROOT=`SHELL='' vkb` loadkmap <"/lib/keymaps/$REAL_ROOT.map" || break done 2>/dev/null set_root_loop "$REAL_ROOT" [ "$REAL_ROOT" = shell ] || continue fi bmsg "failed to switch root" run_shell done fi