[openwrt/openwrt] failsafe: run on all consoles listed in /proc/cmdline

LEDE Commits lede-commits at lists.infradead.org
Sun Jun 19 03:41:11 PDT 2022


chunkeey pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/c9725d4fb62062b42197ff181b87874be336d39f

commit c9725d4fb62062b42197ff181b87874be336d39f
Author: Mark Mentovai <mark at moxienet.com>
AuthorDate: Mon Jun 6 00:59:14 2022 -0400

    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>
---
 .../base-files/files/lib/preinit/30_failsafe_wait  | 60 ++++++++++++----------
 .../files/lib/preinit/99_10_failsafe_login         | 15 +++---
 2 files changed, 40 insertions(+), 35 deletions(-)

diff --git a/package/base-files/files/lib/preinit/30_failsafe_wait b/package/base-files/files/lib/preinit/30_failsafe_wait
index f90de71d40..9ab2e8bd4d 100644
--- a/package/base-files/files/lib/preinit/30_failsafe_wait
+++ b/package/base-files/files/lib/preinit/30_failsafe_wait
@@ -40,35 +40,39 @@ fs_wait_for_key () {
 		rm -f $keypress_wait
 	} &
 
-	[ "$pi_preinit_no_failsafe" != "y" ] && echo "Press the [$1] key and hit [enter] $2"
-	echo "Press the [1], [2], [3] or [4] key and hit [enter] to select the debug level"
-	# if we're on the console we wait for input
-	{
-		while [ -r $keypress_wait ]; do
-			timer="$(cat $keypress_sec)"
+	local consoles="$(sed -e 's/ /\n/g' /proc/cmdline | grep '^console=' | sed -e 's/^console=//' -e 's/,.*//')"
+	[ -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)"
 
-			[ -n "$timer" ] || timer=1
-			timer="${timer%%\ *}"
-			[ $timer -ge 1 ] || timer=1
-			do_keypress=""
-			{
-				read -t "$timer" do_keypress
-				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
-	}
+				[ -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
 	lock -w $keypress_wait
 
 	keypressed=1
diff --git a/package/base-files/files/lib/preinit/99_10_failsafe_login b/package/base-files/files/lib/preinit/99_10_failsafe_login
index 1410c5f0db..6f4af3f28b 100644
--- a/package/base-files/files/lib/preinit/99_10_failsafe_login
+++ b/package/base-files/files/lib/preinit/99_10_failsafe_login
@@ -2,13 +2,14 @@
 # Copyright (C) 2010 Vertical Communications
 
 failsafe_shell() {
-	local console="$(sed -e 's/ /\n/g' /proc/cmdline | grep '^console=' | head -1 | sed -e 's/^console=//' -e 's/,.*//')"
-	[ -n "$console" ] || console=console
-	[ -c "/dev/$console" ] || return 0
-	while true; do
-		ash --login <"/dev/$console" >"/dev/$console" 2>"/dev/$console"
-		sleep 1
-	done &
+	local consoles="$(sed -e 's/ /\n/g' /proc/cmdline | grep '^console=' | sed -e 's/^console=//' -e 's/,.*//')"
+	[ -n "$consoles" ] || consoles=console
+	for console in $consoles; do
+		[ -c "/dev/$console" ] && while true; do
+			ash --login <"/dev/$console" >"/dev/$console" 2>"/dev/$console"
+			sleep 1
+		done &
+	done
 }
 
 boot_hook_add failsafe failsafe_shell




More information about the lede-commits mailing list