I have done a significant reworking of /etc/preinit to make it more modular and customizable. It is now possible to configured things like the failsafe ip. It is also possible to easily customize what happens in preinit and failsafe.
I am working on a project in which use the failsafe mode as way to provide a way to restore to service provider configured settings as well as to do provisioning. By modularizing preinit/failsafe I will be able to make all the generic parts available as a package. In addition anyone else can more easily customize this part of OpenWRT with these changes as needed for a particular application. /etc/preinit.d/conf.d is a directory containing files that are cat'ed and the contents eval'd. /etc/preinit.d/run.d is a directory that contains scripts that may be run. Scripts beginning with failsafe_ are executed when failsafe mode is selected. Scripts beginning with premount_ (currently there are no examples) are run even if there is an initramfs and after that scripts beginning with boot_ are run to bring up the system. In addition I have created menuconfig entries for a number of properties of the preinit/failsafe, and store those settings in files in /etc/preinit.d/conf.d to be used during preinit. Currently I use env - to clear the environment and set the PATH on init. I would appreciate any comments on the changes. -- And that's my crabbing done for the day. Got it out of the way early, now I have the rest of the afternoon to sniff fragrant tea-roses or strangle cute bunnies or something. -- Michael Devore GnuPG Key Fingerprint 86 F5 81 A5 D4 2E 1F 1C http://gnupg.org The C Shore (Daniel Dickinson's Website) http://www.bmts.com/~cshore
Index: scripts/metadata.pl =================================================================== --- scripts/metadata.pl (revision 17208) +++ scripts/metadata.pl (working copy) @@ -533,14 +533,14 @@ sub gen_package_config() { parse_package_metadata($ARGV[0]) or exit 1; - print "menuconfig UCI_PRECONFIG\n\tbool \"Image configuration\"\n" if %preconfig; + print "menuconfig IMAGEOPT\n\tbool \"Image configuration\"\n\tdefault n\nsource \"ImageConfig.in\"\n"; foreach my $preconfig (keys %preconfig) { foreach my $cfg (keys %{$preconfig{$preconfig}}) { my $conf = $preconfig{$preconfig}->{$cfg}->{id}; $conf =~ tr/\.-/__/; print <<EOF config UCI_PRECONFIG_$conf - string "$preconfig{$preconfig}->{$cfg}->{label}" if UCI_PRECONFIG + string "$preconfig{$preconfig}->{$cfg}->{label}" if IMAGEOPT depends PACKAGE_$preconfig default "$preconfig{$preconfig}->{$cfg}->{default}" Index: package/base-files/files/etc/preinit.d/run.d/boot_80_config_restore =================================================================== --- package/base-files/files/etc/preinit.d/run.d/boot_80_config_restore (revision 0) +++ package/base-files/files/etc/preinit.d/run.d/boot_80_config_restore (revision 0) @@ -0,0 +1,12 @@ +# Restore configuration saved during sysupgrade + +boot_80_config_restore () { + [ -f /sysupgrade.tgz ] && { + echo "- config restore -" + cd / + mv sysupgrade.tgz /tmp + tar xzf /tmp/sysupgrade.tgz + rm -f /tmp/sysupgrade.tgz + sync + } +} \ No newline at end of file Index: package/base-files/files/etc/preinit.d/run.d/failsafe_90_session =================================================================== --- package/base-files/files/etc/preinit.d/run.d/failsafe_90_session (revision 0) +++ package/base-files/files/etc/preinit.d/run.d/failsafe_90_session (revision 0) @@ -0,0 +1,5 @@ +# Start failsafe session (default is shell) + +failsafe_90_session () { + ash --login +} Index: package/base-files/files/etc/preinit.d/run.d/boot_20_mount =================================================================== --- package/base-files/files/etc/preinit.d/run.d/boot_20_mount (revision 0) +++ package/base-files/files/etc/preinit.d/run.d/boot_20_mount (revision 0) @@ -0,0 +1,6 @@ +# Mount rootfs filesystem + +boot_20_mount () { + echo "- mount -" + mount_root +} \ No newline at end of file Index: package/base-files/files/etc/preinit.d/run.d/boot_90_init =================================================================== --- package/base-files/files/etc/preinit.d/run.d/boot_90_init (revision 0) +++ package/base-files/files/etc/preinit.d/run.d/boot_90_init (revision 0) @@ -0,0 +1,6 @@ +# run init + +boot_90_init () { + echo "- init -" + exec env - PATH=$INITPATH $INITENV $INITCMD +} \ No newline at end of file Index: package/base-files/files/etc/preinit =================================================================== --- package/base-files/files/etc/preinit (revision 17208) +++ package/base-files/files/etc/preinit (working copy) @@ -4,17 +4,34 @@ . /etc/diag.sh failsafe_ip() { - ifconfig $ifname 192.168.1.1 netmask 255.255.255.0 broadcast 192.168.1.255 up + $fs_failsafe_ip_cmd } +pi_run_scripts() { + # Scripts should contain a function that is the same name as the file + # (which must be a valid function name, e.g. no starting with number) + # The script is source and then this function executed + local pi_script= + local pi_run_funcs= + local pi_run_func= + for pi_script in /etc/preinit.d/run.d/$1*; do + [ -r $pi_script ] && . $pi_script && pi_run_funcs="$pi_run_funcs $(/usr/bin/basename $pi_script)" 2>&1 + done + # We do it this way so that script functions may be overridden + for pi_run_func in $pi_run_funcs; do + $pi_run_func + done +} + failsafe() { - [ -n "$ifname" ] && grep "$ifname" /proc/net/dev >/dev/null && { - failsafe_ip - netmsg 192.168.1.255 "Entering Failsafe!" - telnetd -l /bin/login.sh <> /dev/null 2>&1 + echo "- enter failsafe -" + [ -n "$fs_failsafe_ifname" ] && grep "$fs_failsafe_ifname" /proc/net/dev >/dev/null && { + $fs_failsafe_ip_cmd + $fs_failsafe_echo "Entering Failsafe!" + $fs_failsafe_netcmd } lock /tmp/.failsafe - ash --login + pi_run_scripts failsafe_ } mount proc /proc -t proc @@ -62,28 +79,104 @@ exec <$M0 >$M1 2>&0 echo "- preinit -" -echo "Press CTRL-C for failsafe" -trap 'FAILSAFE=true' INT -trap 'FAILSAFE=true' USR1 + +fs_failsafe_ifname= + [ -e /etc/preinit.arch ] && . /etc/preinit.arch + +if [ -z "$fs_failsafe_ifname" ]; then + fs_failsafe_ifname=$ifname +fi + +fs_failsafe_ip=192.168.1.1 +fs_failsafe_broadcast=192.168.1.255 +fs_failsafe_netmask=255.255.255.0 +fs_failsafe_netcmd="telnetd -l /bin/login.sh <> /dev/null 2>&1" +fs_failsafe_echo="netmsg $fs_failsafe_broadcast" +fs_failsafe_ip_cmd="ifconfig $fs_failsafe_ifname $fs_failsafe_ip netmask $fs_failsafe_netmask broadcast $fs_failsafe_broadcast up" + +[ -d /etc/preinit.d/conf.d ] && \ + OLDIFS="$IFS" ; \ + IFS=' +' ; \ + for fs_variable in $(cat /etc/preinit.d/conf.d/*); do \ + eval $fs_variable ; \ + done + IFS="$OLDIFS" + if [ "$IFS" = "" ]; then + unset IFS + fi + +trap 'echo "1" >/tmp/.failsafe-true; lock -u /tmp/.wait-failsafe ; rm -f /tmp/.wait-failsafe' INT +trap 'echo "1" >/tmp/.failsafe-true; lock -u /tmp/.wait-failsafe ; rm -f /tmp/.wait-failsafe' USR1 + set_state preinit echo "$HOTPLUG" > /proc/sys/kernel/hotplug + +fs_wait_for_key () { + + local TIMEOUT=$fs_timeout + local TIMER= + local DOFAILSAFE + + [ -n "$TIMEOUT" ] || TIMEOUT=1 + TIMEOUT="${TIMEOUT%%\ *}" + [ $TIMEOUT -ge 1 ] || TIMEOUT=1 + TIMER=$TIMEOUT + lock $1 + { + while [ $TIMER -gt 0 ]; do + echo "$TIMER" >/tmp/$2 + TIMER=$(($TIMER - 1)) + sleep 1 + done + lock -u $1 + rm -f $1 + } & + + echo "Press $3<ENTER> for failsafe" + # if we're on the console we wait for input + { + while [ -r $1 ]; do + TIMER="$(cat $2)" + + [ -n "$TIMER" ] || TIMER=1 + TIMER="${TIMER%%\ *}" + [ $TIMER -ge 1 ] || TIMER=1 + { + read -t "$TIMER" DOFAILSAFE + if [ "$DOFAILSAFE" = "$3" ]; then + echo "1" >$4 + lock -u $1 + rm -f $1 + fi + } + done + } + lock -w $1 + + [ "$(cat $4)" = "1" ] && KEYPRESSED=true +} + +fs_wait_for_key /tmp/.fs_waitkey /tmp/.failsafe-wait-sec f /tmp/.failsafe-true + +if [ "$KEYPRESSED" = "true" ]; then + FAILSAFE=true +fi + export FAILSAFE eval ${FAILSAFE:+failsafe} lock -w /tmp/.failsafe + +echo "- regular boot -" -if [ -z "$INITRAMFS" ]; then - mount_root - [ -f /sysupgrade.tgz ] && { - echo "- config restore -" - cd / - mv sysupgrade.tgz /tmp - tar xzf /tmp/sysupgrade.tgz - rm -f /tmp/sysupgrade.tgz - sync - } +rm -f /tmp/.fs_waitkey +rm -f /tmp/.failsafe +rm -f /tmp/.failsafe-wait-sec +rm -f /tmp/.failsafe-true - echo "- init -" - - exec /sbin/init +pi_run_scripts premount_ + +if [ -z "$INITRAMFS" ]; then + pi_run_scripts boot_ fi Index: package/base-files/image-config.in =================================================================== --- package/base-files/image-config.in (revision 0) +++ package/base-files/image-config.in (revision 0) @@ -0,0 +1,79 @@ +menuconfig PREINITOPT + bool "Preinit configuration options" if IMAGEOPT + default n + +config TARGET_PREINIT_TIMEOUT + int + prompt "Failsafe wait timeout" if PREINITOPT + default 5 + help + How long to wait for failsafe mode to be entered before + continuing with a regular boot if failsafe not selected. + +config TARGET_PREINIT_FS_IP + string + prompt "Failsafe IP" if PREINITOPT + default 192.168.1.1 + help + IP address to use for failsafe interface in failsafe mode + +config TARGET_PREINIT_FS_BROADCAST + string + prompt "Failsafe broadcast address" if PREINITOPT + default 192.168.1.255 + help + Broadcast address for log messages in failsafe mode + +config TARGET_PREINIT_FS_NETMASK + string + prompt "Failsafe netmask" if PREINITOPT + default 255.255.255.0 + help + Netmask for failsafe mode + +config TARGET_PREINIT_FS_NETCMD + string + prompt "Failsafe network login server" if PREINITOPT + default "telnetd -l /bin/login.sh <> /dev/null 2>&1" + help + Command for allowing network logins in failsafe mode + +config TARGET_PREINIT_FS_FAILSAFE_ECHO + string + prompt "Failsafe echo (messages/logging)" if PREINITOPT + default "netmsg $$$$fs_failsafe_broadcast" + help + Command to echo output to network for logging etc. + +config TARGET_PREINIT_FS_IP_CMD + string + prompt "Failsafe IP up command" if PREINITOPT + default "ifconfig $$$$fs_failsafe_ifname $$$$fs_failsafe_ip netmask $$$$fs_failsafe_netmask broadcast $$$$fs_failsafe_broadcast up" + help + Command to bring up the failsafe interface and network. + +config TARGET_PREINIT_FS_IFNAME + string + prompt "Failsafe interface" if PREINITOPT + default "" + help + Interface for networking while in failsafe mode + +menuconfig INITOPT + bool "Init configuration options" if IMAGEOPT + default n + + config TARGET_INIT_PATH + string + prompt "PATH for regular boot" if INITOPT + default "/bin:/sbin:/usr/bin:/usr/sbin" + + config TARGET_INIT_ENV + string + prompt "Environment variables to set when starting init (start with none)" if INITOPT + default "HOTPLUG=/sbin/hotplug-call" + + config TARGET_INIT_CMD + string + prompt "Init command" if INITOPT + default "/sbin/init" Index: package/base-files/Makefile =================================================================== --- package/base-files/Makefile (revision 17208) +++ package/base-files/Makefile (working copy) @@ -140,6 +140,20 @@ $(call Build/Compile/Default) endef +define ImageConfigOptions + echo 'fs_timeout=$(if $(CONFIG_TARGET_PREINIT_TIMEOUT),$(CONFIG_TARGET_PREINIT_TIMEOUT),5)' >$(1)/etc/preinit.d/conf.d/00_fs_timeout + echo 'fs_failsafe_ip=$(if $(CONFIG_TARGET_PREINIT_FS_IP),$(CONFIG_TARGET_PREINIT_FS_IP),"192.168.1.1")' >$(1)/etc/preinit.d/conf.d/10_fs_failsafe_net + echo 'fs_failsafe_broadcast=$(if $(CONFIG_TARGET_PREINIT_FS_BROADCAST),$(CONFIG_TARGET_PREINIT_FS_BROADCAST),"192.168.1.255")' >>$(1)/etc/preinit.d/conf.d/10_fs_failsafe_net + echo 'fs_failsafe_netmask=$(if $(CONFIG_TARGET_PREINIT_FS_NETMASK),$(CONFIG_TARGET_PREINIT_FS_NETMASK),"255.255.255.0")' >>$(1)/etc/preinit.d/conf.d/10_fs_failsafe_net + echo 'fs_failsafe_netcmd=$(if $(CONFIG_TARGET_PREINIT_FS_NETCMD),$(CONFIG_TARGET_PREINIT_FS_NETCMD),"telnetd -l /bin/login.sh \<\> /dev/null 2\>\&1")' >>$(1)/etc/preinit.d/conf.d/10_fs_failsafe_net + echo 'fs_failsafe_ifname=$(if $(CONFIG_TARGET_PREINIT_FS_IFNAME),$(CONFIG_TARGET_PREINIT_FS_IFNAME),"")' >>$(1)/etc/preinit.d/conf.d/10_fs_failsafe_net + echo 'fs_failsafe_echo=$(if $(CONFIG_TARGET_PREINIT_FS_FAILSAFE_ECHO),$(CONFIG_TARGET_PREINIT_FS_FAILSAFE_ECHO),"netmsg $$$$fs_failsafe_ifname")' >>$(1)/etc/preinit.d/conf.d/10_fs_failsafe_net + echo 'fs_failsafe_ip_cmd=$(if $(CONFIG_TARGET_PREINIT_FS_IP_CMD),$(CONFIG_TARGET_PREINIT_FS_IP_CMD), "ifconfig $$$$fs_failsafe_ifname $$$$fs_failsafe_ip netmask $$$$fs_failsafe_netmask broadcast $$$$fs_failsafe_broadcast up")' >>$(1)/etc/preinit.d/conf.d/10_fs_failsafe_net + echo 'INITPATH=$(if $(CONFIG_TARGET_INIT_PATH),$(CONFIG_TARGET_INIT_PATH),"/bin:/sbin:/usr/bin:/usr/sbin")' >$(1)/etc/preinit.d/conf.d/90_init_path + echo 'INITENV=$(if $(CONFIG_TARGET_INIT_ENV),$(CONFIG_TARGET_INIT_ENV),"")' >$(1)/etc/preinit.d/conf.d/90_init_env + echo 'INITCMD=$(if $(CONFIG_TARGET_INIT_CMD),$(CONFIG_TARGET_INIT_CMD),"/sbin/init")' >$(1)/etc/preinit.d/conf.d/95_init_cmd +endef + define Package/base-files$(TARGET)/install $(CP) ./files/* $(1)/ if [ -d $(GENERIC_PLATFORM_DIR)/base-files/. ]; then \ @@ -193,6 +207,7 @@ ln -sf /tmp $(1)/var mkdir -p $(1)/etc ln -sf /tmp/resolv.conf /tmp/fstab /tmp/TZ $(1)/etc/ + $(call ImageConfigOptions,$(1)) $(call Package/base-files/install-target,$(1)) for conffile in $(1)/etc/config/*; do \ if [ -f "$$$$conffile" ]; then \
signature.asc
Description: PGP signature
_______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/mailman/listinfo/openwrt-devel