I have been continuing to bang away at this and have come up with some improvements and more features for the preinit. I hope you like them. As always I look forward to your comments when you get the time to look at it. I'm hoping that won't be *too* far in future since I'd like to see it in the tree for a while before 8.10 (well that might be a while, so maybe I should just say soonish).
The attached patch replaces my previous one for failsafe/preinit. * I have removed ImageConfig.in and put the code for sourcing the menuconfig files directly in scripts/metadata.pl (so that the config options can be added to the Image configuration" menu, which is defined there). * I have moved additional portions of failsafe and preinit to the modular system * I have added 'preinit_echo' so that messages may be broadcast to the network in preinit, most notably the messages saying to press reset to enter failsafe, and the message which indicates we've entered failsafe or gone on to a regular boot * I've added an config option to allow stderr to be displayed in preinit (currently stderr is suppressed for a cleaner bootlog) for debugging purposes, as was as an option to suppress the stderr for init even if not suppressed for preinit (not that doesn't suppress scripts run by rcS, which uses a tty) * I've genericized the wait for keypress to enter failsafe for use as a function by other parts of preinit...in my next message I you will see how I have used it to allow one to do either a traditional failsafe, or an autorestore firmware and defaults failsafe, after having selected failsafe * I think I've improved the handling of failsafe and preinit network settings, and also of configuration value setting * init's path and environment can be configured -- 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 17239) +++ scripts/metadata.pl (working copy) @@ -533,20 +533,24 @@ 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\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}" EOF } } + print "source \"package/*/image-config.in\"\n"; + if (scalar glob "package/feeds/*/*/image-config.in") { + print "source \"package/feeds/*/*/image-config.in\"\n"; + } print_package_config_category 'Base system'; foreach my $cat (keys %category) { print_package_config_category $cat; Index: package/base-files/files/etc/preinit.d/run.d/failsafe_80_netlogin =================================================================== --- package/base-files/files/etc/preinit.d/run.d/failsafe_80_netlogin (revision 0) +++ package/base-files/files/etc/preinit.d/run.d/failsafe_80_netlogin (revision 0) @@ -0,0 +1,8 @@ +#!/bin/sh +# Copyright (C) 2009 OpenWrt.org + +# Allow network logins in failsafe mode + +failsafe_80_netlogin () { + telnetd -l /bin/login.sh <> /dev/null 2>&1 +} \ No newline at end of file Index: package/base-files/files/etc/preinit.d/run.d/preinit_base_30_failsafe_entry =================================================================== --- package/base-files/files/etc/preinit.d/run.d/preinit_base_30_failsafe_entry (revision 0) +++ package/base-files/files/etc/preinit.d/run.d/preinit_base_30_failsafe_entry (revision 0) @@ -0,0 +1,30 @@ +#!/bin/sh +# Copyright (C) 2009 OpenWrt.org + +# determine if failsafe mode is desired, and if so, enter it + +preinit_base_30_failsafe_entry () { + FAILSAFE=false + + preinit_ip + preinit_echo "Please reset now to enter Failsafe!" + + fs_wait_for_key "f" "to enter failsafe" $fs_timeout + + if [ "$?" = "1" ]; then + FAILSAFE=true + else + preinit_echo "Continuing with regular boot" + fi + + preinit_ip_deconfig + + export FAILSAFE + + if [ "$FAILSAFE" = "true" ]; then + failsafe + fi + lock -w /tmp/.failsafe + + echo "- regular boot -" +} \ No newline at end of file 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,15 @@ +#!/bin/sh +# Copyright (C) 2009 OpenWrt.org + +# 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,8 @@ +#!/bin/sh +# Copyright (C) 2009 OpenWrt.org + +# 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,9 @@ +#!/bin/sh +# Copyright (C) 2009 OpenWrt.org + +# 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/failsafe_20_enter_failsafe_message =================================================================== --- package/base-files/files/etc/preinit.d/run.d/failsafe_20_enter_failsafe_message (revision 0) +++ package/base-files/files/etc/preinit.d/run.d/failsafe_20_enter_failsafe_message (revision 0) @@ -0,0 +1,7 @@ +#!/bin/sh +# Copyright (C) 2009 OpenWrt.org + +failsafe_20_enter_failsafe_message () { + failsafe_ip + failsafe_echo "Entering Failsafe!" +} \ No newline at end of file Index: package/base-files/files/etc/preinit.d/run.d/failsafe_10_echo =================================================================== --- package/base-files/files/etc/preinit.d/run.d/failsafe_10_echo (revision 0) +++ package/base-files/files/etc/preinit.d/run.d/failsafe_10_echo (revision 0) @@ -0,0 +1,21 @@ +#!/bin/sh +# Copyright (C) 2009 OpenWrt.org + +# commands for emitting messages to network in failsafe mode + +failsafe_ip () { + [ -n "$fs_failsafe_ifname" ] && grep "$fs_failsafe_ifname" /proc/net/dev >/dev/null && { + /bin/ifconfig $fs_failsafe_ifname $fs_failsafe_ip netmask $fs_failsafe_netmask broadcast $fs_failsafe_broadcast up + } +} + +failsafe_echo () { + [ -n "$fs_failsafe_ifname" ] && grep "$fs_failsafe_ifname" /proc/net/dev >/dev/null && { + netmsg $fs_failsafe_broadcast "$1" + } +} + +failsafe_10_echo () { + : + # dummy function to satisfy pi_run_scripts +} \ No newline at end of file Index: package/base-files/files/etc/preinit.d/run.d/preinit_base_10_preinit_echo =================================================================== --- package/base-files/files/etc/preinit.d/run.d/preinit_base_10_preinit_echo (revision 0) +++ package/base-files/files/etc/preinit.d/run.d/preinit_base_10_preinit_echo (revision 0) @@ -0,0 +1,27 @@ +#!/bin/sh +# Copyright (C) 2009 OpenWrt.org + +# commands for emitting messages to network for preinit + +preinit_ip () { + [ -n "$pi_ifname" ] && grep "$pi_ifname" /proc/net/dev >/dev/null && { + ifconfig $pi_ifname $pi_ip netmask $pi_netmask broadcast $pi_broadcast up + } +} + +preinit_ip_deconfig () { + [ -n "$pi_ifname" ] && grep "$pi_ifname" /proc/net/dev >/dev/null && { + ifconfig $pi_ifname down + } +} + +preinit_echo () { + [ -n "$pi_ifname" ] && grep "$pi_ifname" /proc/net/dev >/dev/null && { + netmsg $pi_broadcast "$1" + } +} + +preinit_base_10_preinit_echo () { + : + # dummy function to satisfy pi_run_scripts +} 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,13 @@ +#!/bin/sh +# Copyright (C) 2009 OpenWrt.org + +# run init + +boot_90_init () { + echo "- init -" + if [ "$INITSTDERR_SUPPRESS" = "y" ]; then + exec env - PATH=$INITPATH $INITENV $INITCMD 2>&0 + else + exec env - PATH=$INITPATH $INITENV $INITCMD + fi +} \ No newline at end of file Index: package/base-files/files/etc/preinit =================================================================== --- package/base-files/files/etc/preinit (revision 17239) +++ package/base-files/files/etc/preinit (working copy) @@ -3,20 +3,100 @@ export PATH=/bin:/sbin:/usr/bin:/usr/sbin . /etc/diag.sh -failsafe_ip() { - ifconfig $ifname 192.168.1.1 netmask 255.255.255.0 broadcast 192.168.1.255 up +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 -" lock /tmp/.failsafe - ash --login + pi_run_scripts failsafe_ } +fs_wait_for_key () { + + local TIMEOUT=$3 + local TIMER= + local DOFAILSAFE= + local KEYPRESS_TRUE="$(mktemp)" + local KEYPRESS_WAIT="$(mktemp)" + local KEYPRESS_SEC="$(mktemp)" + if [ -z "$KEYPRESS_WAIT" ]; then + KEYPRESS_WAIT=/tmp/.keypress_wait + touch $KEYPRESS_WAIT + fi + if [ -z "$KEYPRESS_TRUE" ]; then + KEYPRESS_TRUE=/tmp/.keypress_true + touch $KEYPRESS_TRUE + fi + if [ -z "$KEYPRESS_SEC" ]; then + KEYPRESS_SEC=/tmp/.keypress_sec + touch $KEYPRESS_SEC + fi + + trap "echo '1' >$KEYPRESS_TRUE; lock -u $KEYPRESS_WAIT ; rm -f $KEYRPESS_WAIT'" INT + trap "echo '1' >$KEYRPESS_TRUE; lock -u $KEYRPESS_WAIT ; rm -f $KEYPRESS_WAIT'" USR1 + + [ -n "$TIMEOUT" ] || TIMEOUT=1 + [ $TIMEOUT -ge 1 ] || TIMEOUT=1 + TIMER=$TIMEOUT + lock $KEYPRESS_WAIT + { + while [ $TIMER -gt 0 ]; do + echo "$TIMER" >$KEYPRESS_SEC + TIMER=$(($TIMER - 1)) + sleep 1 + done + lock -u $KEYPRESS_WAIT + rm -f $KEYPRESS_WAIT + } & + + echo "Press $1<ENTER> $2" + # if we're on the console we wait for input + { + while [ -r $KEYPRESS_WAIT ]; do + TIMER="$(cat $KEYPRESS_SEC)" + + [ -n "$TIMER" ] || TIMER=1 + TIMER="${TIMER%%\ *}" + [ $TIMER -ge 1 ] || TIMER=1 + DOFAILSAFE="" + { + read -t "$TIMER" DOFAILSAFE + if [ "$DOFAILSAFE" = "$1" ]; then + echo "1" >$KEYPRESS_TRUE + lock -u $KEYPRESS_WAIT + rm -f $KEYPRESS_WAIT + fi + } + done + } + lock -w $KEYPRESS_WAIT + + trap - INT + trap - USR1 + + KEYPRESSED=0 + [ "$(cat $KEYPRESS_TRUE)" = "1" ] && KEYPRESSED=1 + rm -f $KEYPRESS_TRUE + rm -f $KEYPRESS_WAIT + rm -f $KEYPRESS_SEC + + return $KEYPRESSED +} + mount proc /proc -t proc mount sysfs /sys -t sysfs @@ -27,6 +107,7 @@ mount devfs /dev -t devfs M0=/dev/pty/m0 M1=/dev/pty/m1 + M2=/dev/pty/m1 HOTPLUG=/sbin/hotplug-call elif [ -x /sbin/hotplug2 ]; then @@ -36,6 +117,7 @@ /sbin/hotplug2 --set-worker /lib/hotplug2/worker_fork.so --set-rules-file /etc/hotplug2-init.rules --persistent & M0=/dev/ptmx M1=/dev/ptmx + M2=/dev/ptmx HOTPLUG= elif [ -x /sbin/udevd ]; then @@ -45,6 +127,7 @@ /sbin/udevsettle M0=/dev/pty/ptmx M1=/dev/pty/ptmx + M2=/dev/pty/ptmx HOTPLUG= fi @@ -57,33 +140,59 @@ dd if=/dev/console of=/dev/null bs=1 count=0 >/dev/null 2>/dev/null && { M0=/dev/console M1=/dev/console + M2=/dev/console } -exec <$M0 >$M1 2>&0 +[ -r /etc/preinit.d/pi_base_conf ] && . /etc/preinit.d/pi_base_conf +if [ "$pi_suppress_stderr" = "y" ]; then + exec <$M0 >$M1 2>&0 +else + exec <$M0 >$M1 2>$M2 +fi + echo "- preinit -" -echo "Press CTRL-C for failsafe" -trap 'FAILSAFE=true' INT -trap 'FAILSAFE=true' USR1 + +fs_failsafe_ifname= +pi_ifname= + [ -e /etc/preinit.arch ] && . /etc/preinit.arch set_state preinit echo "$HOTPLUG" > /proc/sys/kernel/hotplug -export FAILSAFE -eval ${FAILSAFE:+failsafe} -lock -w /tmp/.failsafe -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 - } +pi_ip=192.168.1.1 +pi_broadcast=192.168.1.255 +pi_netmask=255.255.255.0 +fs_failsafe_ip=192.168.1.1 +fs_failsafe_broadcast=192.168.1.255 +fs_failsafe_netmask=255.255.255.0 - echo "- init -" - - exec /sbin/init +if [ -z "$fs_failsafe_ifname" ]; then + fs_failsafe_ifname=$ifname fi + +if [ -z "$pi_ifname" ]; then + pi_ifname=$ifname +fi + +# We use backslash continuation not braces to avoid scope issues +# for variable assignments +[ -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 + +pi_run_scripts preinit_base_ + +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,115 @@ +# Copyright (C) 2009 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +menuconfig PREINITOPT + bool "Preinit configuration options" if IMAGEOPT + default n + +config TARGET_PREINIT_SUPPRESS_STDERR + bool "Suppress stderr messages during preinit" if PREINITOPT + default y + help + Sends stderr to null during preinit. This is the default behaviour + in previous versions of OpenWRT. This also prevents init process + itself from display stderr, but once multiuser is entered, stderr may + be sent to a tty and thus appear (that's the default behaviour). + +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_IFNAME + string + prompt "Preinit network message interface" if PREINITOPT + default "" + help + Interface for sending preinit messages to network. If empty + uses $ifname (if defined in /etc/preinit.arch). + +config TARGET_PREINIT_IP + string + prompt "IP address for preinit network messages" if PREINITOPT + default "192.168.1.1" + help + IP address used to configure interface for preinit network + messages. + +config TARGET_PREINIT_NETMASK + string + prompt "Netmask for preinit network messages" if PREINITOPT + default "255.255.255.0" + help + Netmask used to configure interface for preinit network + messages + +config TARGET_PREINIT_BROADCAST + string + prompt "Broadcast address for preinit network messages" if PREINITOPT + default "192.168.1.255 + help + Broadcast address to which to send preinit network messages + +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_IFNAME + string + prompt "Failsafe interface" if PREINITOPT + default "" + help + Interface for networking while in failsafe mode. If empty + uses $ifname (if defined in /etc/preinit.arch). + +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 "" + + config TARGET_INIT_CMD + string + prompt "Init command" if INITOPT + default "/sbin/init" + + config TARGET_INIT_SUPPRESS_STDERR + bool + prompt "Suppress stderr messages of init" if INITOPT + default y + help + Prevents showing stderr messages for init command if not already + suppressed during preinit. This is the default behaviour in previous + versions of OpenWRT. Removing this does nothing if stderr is + suppressed during preinit (the default). Index: package/base-files/Makefile =================================================================== --- package/base-files/Makefile (revision 17239) +++ package/base-files/Makefile (working copy) @@ -140,6 +140,24 @@ $(call Build/Compile/Default) endef +define ImageConfigOptions + mkdir -p $(1)/etc/preinit.d/conf.d + echo 'pi_suppress_stderr="$(CONFIG_TARGET_PREINIT_SUPPRESS_STDERR)"' >$(1)/etc/preinit.d/pi_base_conf + 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_ifname=$(if $(CONFIG_TARGET_PREINIT_FS_IFNAME),$(CONFIG_TARGET_PREINIT_FS_IFNAME),"")' >>$(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 + echo 'INITSTDERR_SUPPRESS="$(CONFIG_TARGET_INIT_SUPPRESS_STDERR)"' >>$(1)/etc/preinit.d/conf.d/90_init_env + echo 'pi_ifname=$(if $(CONFIG_TARGET_PREINIT_IFNAME),$(CONFIG_TARGET_PREINIT_IFNAME),"")' >$(1)/etc/preinit.d/conf.d/10_preinit_netmsg + echo 'pi_ip=$(if $(CONFIG_TARGET_PREINIT_IP),$(CONFIG_TARGET_PREINIT_IP),"192.168.1.1")' >>$(1)/etc/preinit.d/conf.d/10_preinit_netmsg + echo 'pi_netmask=$(if $(CONFIG_TARGET_PREINIT_NETMASK),$(CONFIG_TARGET_PREINIT_NETMASK),"255.255.255.0")' >>$(1)/etc/preinit.d/conf.d/10_preinit_netmsg + echo 'pi_broadcast=$(if $(CONFIG_TARGET_PREINIT_BROADCAST),$(CONFIG_TARGET_PREINIT_BROADCAST),"")' >>$(1)/etc/preinit.d/conf.d/10_preinit_netmsg +endef + define Package/base-files$(TARGET)/install $(CP) ./files/* $(1)/ if [ -d $(GENERIC_PLATFORM_DIR)/base-files/. ]; then \ @@ -193,6 +211,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