2010-01-25 17:11:17 +00:00
|
|
|
# Copyright (C) 2006-2010 OpenWrt.org
|
|
|
|
# Copyright (C) 2010 Vertical Communications
|
|
|
|
|
|
|
|
fs_wait_for_key () {
|
2013-12-09 11:30:14 +00:00
|
|
|
local timeout=$3
|
|
|
|
local timer
|
|
|
|
local do_keypress
|
|
|
|
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
|
2010-01-25 17:11:17 +00:00
|
|
|
|
2013-12-09 11:30:14 +00:00
|
|
|
trap "echo 'true' >$keypress_true; lock -u $keypress_wait ; rm -f $keypress_wait" INT
|
|
|
|
trap "echo 'true' >$keypress_true; lock -u $keypress_wait ; rm -f $keypress_wait" USR1
|
2010-01-25 17:11:17 +00:00
|
|
|
|
2013-12-09 11:30:14 +00:00
|
|
|
[ -n "$timeout" ] || timeout=1
|
|
|
|
[ $timeout -ge 1 ] || timeout=1
|
|
|
|
timer=$timeout
|
|
|
|
lock $keypress_wait
|
|
|
|
{
|
|
|
|
while [ $timer -gt 0 ]; do
|
2019-12-10 14:24:20 +00:00
|
|
|
pi_failsafe_net_message=true \
|
|
|
|
preinit_net_echo "Please press button now to enter failsafe"
|
2013-12-09 11:30:14 +00:00
|
|
|
echo "$timer" >$keypress_sec
|
|
|
|
timer=$(($timer - 1))
|
|
|
|
sleep 1
|
|
|
|
done
|
2013-11-25 08:34:55 +00:00
|
|
|
lock -u $keypress_wait
|
|
|
|
rm -f $keypress_wait
|
2013-12-09 11:30:14 +00:00
|
|
|
} &
|
|
|
|
|
failsafe: fix console failsafe shell
When running a failsafe shell on a console, job control was unavailable,
and ^C did not function correctly.
This change invokes console failsafe shells via `setsid`, making them
session leaders and allowing them to claim controlling terminals, which
makes job control function properly. To support this, the busybox
`setsid` utility is enabled. This has a minimal 149-byte size impact on
a test x86_64 squashfs rootfs image.
^C was ignored in subprocesses of failsafe shells: it was not possible
to ^C out of a program that would not exit on its own, such as many
typical `ping` invocations. As job control was unavailable, it was not
possible to suspend these subprocesses either, causing a hung program to
tie up a console indefinitely, unless another means to signal the
program was available. This was caused by SIGINT being placed at
disposition SIG_IGN by the shell running preinit, which it did because
the console shell was executed asynchronously with &. That disposition
was inherited by the console shell and its subprocesses, generally
causing ^C to have no effect.
As there is no way in busybox `ash` to reset the disposition of a signal
already ignored at shell entry, and no apparent way to avoid SIGINT
being placed at SIG_IGN when & is used in preinit, an alternative
construct is needed. Now, `start-stop-daemon` is used to start (-S) the
console failsafe shell in the background (-b). This approach does not
alter SIGINT, allowing the console shell to be started with that
signal's handling intact, and normal ^C processing to occur.
busybox `ash` has some behaviors conditional on SHLVL, and while the
console shells ought to run at SHLVL=1, they were not by virtue of being
started by the shell-based preinit system. Additionally, a variety of
detritus was present in the console shell's environment, carried over
from preinit. These conditions are corrected by running the console
shell via `env -i` to clear the environment and establish a minimum and
correct set of environment variables for operation, in the same manner
as `login`. HOME is not explicitly set, because it's addressed in
/etc/profile. For non-failsafe console shells when
system.@system[0].ttylogin = 0, `login -f root` achieves a similar
effect. (`login` already started non-failsafe console shells when
ttylogin = 1 and behaved correctly. This brings the ttylogin = 0 case to
parity.) Note that even `login -f` is somewhat undesirable for failsafe
shells because it requires a viable /etc/passwd, hence the `env -i`
construct in that case.
The TERM environment variable from the preinit environment, with value
"linux", would rarely be correct for serial consoles. Now, the preinit
TERM value is preserved (or set to "linux" if unset) only when the
console is /dev/console or /dev/tty[0-9]*. Otherwise, it will be set to
a safe default appropriate for serial consoles, "vt102", as used for
serial consoles by busybox init. This "linux"/"vt102" TERM setting is
also duplicated for non-failsafe console shells.
This also indicates failsafe mode by showing "- failsafe -" on all
consoles (not just the last-defined one). It sets a hostname of
"OpenWrt-failsafe" in failsafe mode which is rendered in the shell's
prompt as a reminder of the mode during interactive failsafe use.
Previously, no hostname was set, which resulted in the kernel-default
hostname, "(none)", appearing in failsafe shell prompts.
Signed-off-by: Mark Mentovai <mark@mentovai.com>
Link: https://github.com/openwrt/openwrt/pull/16113
Signed-off-by: Robert Marko <robimarko@gmail.com>
2022-06-06 18:53:31 +00:00
|
|
|
local consoles="$(cat /sys/class/tty/console/active)"
|
failsafe: run on all consoles listed in /proc/cmdline
On x86, when both CONFIG_GRUB_CONSOLE and CONFIG_GRUB_SERIAL are set (as
they are by default), the kernel command line will have two console=
entries, such as
console=tty0 console=ttyS0,115200n8
Failsafe was only running a shell on the first defined console, the VGA
console. This is a problem for devices like apu2, where there is only a
serial console and it appears on ttyS0.
Moreover, the console prompt to enter failsafe during boot was delivered
to, and its input read from, the last console= on the kernel command
line. So while the failsafe shell was on the first defined console, only
the last defined console could be used to enter failsafe during boot.
In contrast, the x86 bootloader (GRUB) operates on both the serial
console and the VGA console by virtue of "terminal_{input,output}
console serial". GRUB also provided an alternate means to enter failsafe
from either console. The presence of two console= kernel command line
parameters causes kernel messages to be delivered to both. Under normal
operation (not failsafe), procd runs login in accordance with inittab,
which on x86 specifies ttyS0, hvc0, and tty1, allowing login through any
of serial, hypervisor, or VGA console. Thus, serial access was
consistently available on x86 devices with serial consoles under normal
operation, except for shell access in failsafe mode (without editing the
kernel command line).
By presenting the failsafe prompt, reading failsafe prompt input, and
running failsafe shells on all consoles listed in /proc/cmdline,
failsafe mode will work correctly on devices with a serial console (like
apu2), and the same image without any need for reconfiguration can be
shared by devices with the more traditional (for x86) VGA console. This
improvement should benefit any system with multiple console= arguments,
including x86 and bcm27xx (Raspberry Pi).
Signed-off-by: Mark Mentovai <mark at moxienet.com>
2022-06-06 04:59:14 +00:00
|
|
|
[ -n "$consoles" ] || consoles=console
|
|
|
|
for console in $consoles; do
|
|
|
|
[ -c "/dev/$console" ] || continue
|
|
|
|
[ "$pi_preinit_no_failsafe" != "y" ] && echo "Press the [$1] key and hit [enter] $2" > "/dev/$console"
|
|
|
|
echo "Press the [1], [2], [3] or [4] key and hit [enter] to select the debug level" > "/dev/$console"
|
|
|
|
{
|
|
|
|
while [ -r $keypress_wait ]; do
|
|
|
|
timer="$(cat $keypress_sec)"
|
2013-12-09 11:30:14 +00:00
|
|
|
|
failsafe: run on all consoles listed in /proc/cmdline
On x86, when both CONFIG_GRUB_CONSOLE and CONFIG_GRUB_SERIAL are set (as
they are by default), the kernel command line will have two console=
entries, such as
console=tty0 console=ttyS0,115200n8
Failsafe was only running a shell on the first defined console, the VGA
console. This is a problem for devices like apu2, where there is only a
serial console and it appears on ttyS0.
Moreover, the console prompt to enter failsafe during boot was delivered
to, and its input read from, the last console= on the kernel command
line. So while the failsafe shell was on the first defined console, only
the last defined console could be used to enter failsafe during boot.
In contrast, the x86 bootloader (GRUB) operates on both the serial
console and the VGA console by virtue of "terminal_{input,output}
console serial". GRUB also provided an alternate means to enter failsafe
from either console. The presence of two console= kernel command line
parameters causes kernel messages to be delivered to both. Under normal
operation (not failsafe), procd runs login in accordance with inittab,
which on x86 specifies ttyS0, hvc0, and tty1, allowing login through any
of serial, hypervisor, or VGA console. Thus, serial access was
consistently available on x86 devices with serial consoles under normal
operation, except for shell access in failsafe mode (without editing the
kernel command line).
By presenting the failsafe prompt, reading failsafe prompt input, and
running failsafe shells on all consoles listed in /proc/cmdline,
failsafe mode will work correctly on devices with a serial console (like
apu2), and the same image without any need for reconfiguration can be
shared by devices with the more traditional (for x86) VGA console. This
improvement should benefit any system with multiple console= arguments,
including x86 and bcm27xx (Raspberry Pi).
Signed-off-by: Mark Mentovai <mark at moxienet.com>
2022-06-06 04:59:14 +00:00
|
|
|
[ -n "$timer" ] || timer=1
|
|
|
|
timer="${timer%%\ *}"
|
|
|
|
[ $timer -ge 1 ] || timer=1
|
|
|
|
do_keypress=""
|
|
|
|
{
|
|
|
|
read -t "$timer" do_keypress < "/dev/$console"
|
|
|
|
case "$do_keypress" in
|
|
|
|
$1)
|
|
|
|
echo "true" >$keypress_true
|
|
|
|
;;
|
|
|
|
1 | 2 | 3 | 4)
|
|
|
|
echo "$do_keypress" >/tmp/debug_level
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
continue;
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
lock -u $keypress_wait
|
|
|
|
rm -f $keypress_wait
|
|
|
|
}
|
|
|
|
done
|
|
|
|
} &
|
|
|
|
done
|
2013-12-09 11:30:14 +00:00
|
|
|
lock -w $keypress_wait
|
2010-01-25 17:11:17 +00:00
|
|
|
|
2013-12-09 11:30:14 +00:00
|
|
|
keypressed=1
|
|
|
|
[ "$(cat $keypress_true)" = "true" ] && keypressed=0
|
|
|
|
|
failsafe: fix console failsafe shell
When running a failsafe shell on a console, job control was unavailable,
and ^C did not function correctly.
This change invokes console failsafe shells via `setsid`, making them
session leaders and allowing them to claim controlling terminals, which
makes job control function properly. To support this, the busybox
`setsid` utility is enabled. This has a minimal 149-byte size impact on
a test x86_64 squashfs rootfs image.
^C was ignored in subprocesses of failsafe shells: it was not possible
to ^C out of a program that would not exit on its own, such as many
typical `ping` invocations. As job control was unavailable, it was not
possible to suspend these subprocesses either, causing a hung program to
tie up a console indefinitely, unless another means to signal the
program was available. This was caused by SIGINT being placed at
disposition SIG_IGN by the shell running preinit, which it did because
the console shell was executed asynchronously with &. That disposition
was inherited by the console shell and its subprocesses, generally
causing ^C to have no effect.
As there is no way in busybox `ash` to reset the disposition of a signal
already ignored at shell entry, and no apparent way to avoid SIGINT
being placed at SIG_IGN when & is used in preinit, an alternative
construct is needed. Now, `start-stop-daemon` is used to start (-S) the
console failsafe shell in the background (-b). This approach does not
alter SIGINT, allowing the console shell to be started with that
signal's handling intact, and normal ^C processing to occur.
busybox `ash` has some behaviors conditional on SHLVL, and while the
console shells ought to run at SHLVL=1, they were not by virtue of being
started by the shell-based preinit system. Additionally, a variety of
detritus was present in the console shell's environment, carried over
from preinit. These conditions are corrected by running the console
shell via `env -i` to clear the environment and establish a minimum and
correct set of environment variables for operation, in the same manner
as `login`. HOME is not explicitly set, because it's addressed in
/etc/profile. For non-failsafe console shells when
system.@system[0].ttylogin = 0, `login -f root` achieves a similar
effect. (`login` already started non-failsafe console shells when
ttylogin = 1 and behaved correctly. This brings the ttylogin = 0 case to
parity.) Note that even `login -f` is somewhat undesirable for failsafe
shells because it requires a viable /etc/passwd, hence the `env -i`
construct in that case.
The TERM environment variable from the preinit environment, with value
"linux", would rarely be correct for serial consoles. Now, the preinit
TERM value is preserved (or set to "linux" if unset) only when the
console is /dev/console or /dev/tty[0-9]*. Otherwise, it will be set to
a safe default appropriate for serial consoles, "vt102", as used for
serial consoles by busybox init. This "linux"/"vt102" TERM setting is
also duplicated for non-failsafe console shells.
This also indicates failsafe mode by showing "- failsafe -" on all
consoles (not just the last-defined one). It sets a hostname of
"OpenWrt-failsafe" in failsafe mode which is rendered in the shell's
prompt as a reminder of the mode during interactive failsafe use.
Previously, no hostname was set, which resulted in the kernel-default
hostname, "(none)", appearing in failsafe shell prompts.
Signed-off-by: Mark Mentovai <mark@mentovai.com>
Link: https://github.com/openwrt/openwrt/pull/16113
Signed-off-by: Robert Marko <robimarko@gmail.com>
2022-06-06 18:53:31 +00:00
|
|
|
trap - INT
|
|
|
|
trap - USR1
|
|
|
|
|
2013-12-09 11:30:14 +00:00
|
|
|
rm -f $keypress_true
|
|
|
|
rm -f $keypress_wait
|
|
|
|
rm -f $keypress_sec
|
|
|
|
|
|
|
|
return $keypressed
|
2010-01-25 17:11:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
failsafe_wait() {
|
2013-12-09 11:30:14 +00:00
|
|
|
FAILSAFE=
|
2018-12-04 22:12:05 +00:00
|
|
|
[ "$pi_preinit_no_failsafe" = "y" ] && {
|
2016-04-19 08:07:35 +00:00
|
|
|
fs_wait_for_key "" "" $fs_failsafe_wait_timeout
|
|
|
|
return
|
|
|
|
}
|
2013-12-09 11:30:14 +00:00
|
|
|
grep -q 'failsafe=' /proc/cmdline && FAILSAFE=true && export FAILSAFE
|
|
|
|
if [ "$FAILSAFE" != "true" ]; then
|
|
|
|
fs_wait_for_key f 'to enter failsafe mode' $fs_failsafe_wait_timeout && FAILSAFE=true
|
2020-05-10 14:47:46 +00:00
|
|
|
[ -f "/tmp/failsafe_button" ] && FAILSAFE=true && echo "- failsafe button "$(cat /tmp/failsafe_button)" was pressed -"
|
2013-12-09 11:30:14 +00:00
|
|
|
[ "$FAILSAFE" = "true" ] && export FAILSAFE && touch /tmp/failsafe
|
|
|
|
fi
|
2010-01-25 17:11:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
boot_hook_add preinit_main failsafe_wait
|