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 \

Attachment: signature.asc
Description: PGP signature

_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to