[U-Boot] [PATCH] efi_loader: Fix serial console size detection

matthias.bgg at kernel.org matthias.bgg at kernel.org
Tue Feb 26 11:46:09 UTC 2019


From: Matthias Brugger <mbrugger at suse.com>

Function term_read_reply tries to read from the serial console until
the end_char was read. This can hang forever if we are, for some reason,
not be able to read the full response (e.g. serial buffer too small,
frame error). This patch moves the timeout detection into
term_read_reply to assure we will make progress.

Fixes: 6bb591f704 ("efi_loader: query serial console size reliably")
Signed-off-by: Matthias Brugger <mbrugger at suse.com>
---
 lib/efi_loader/efi_console.c | 63 +++++++++++++++++++++---------------
 1 file changed, 37 insertions(+), 26 deletions(-)

diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c
index 66c33a551d..817220455f 100644
--- a/lib/efi_loader/efi_console.c
+++ b/lib/efi_loader/efi_console.c
@@ -62,6 +62,16 @@ static struct simple_text_output_mode efi_con_mode = {
 	.cursor_visible = 1,
 };
 
+static int term_get_char(char *c)
+{
+	if (tstc()) {
+		*c = getc();
+		return 0;
+	}
+
+	return 1;
+}
+
 /*
  * Receive and parse a reply from the terminal.
  *
@@ -74,32 +84,42 @@ static int term_read_reply(int *n, int num, char end_char)
 {
 	char c;
 	int i = 0;
+	u64 timeout;
 
-	c = getc();
-	if (c != cESC)
+	/* Allow up to one second for the response */
+	timeout = timer_get_us() + 1000000;
+	while (!tstc())
+		if (timer_get_us() > timeout)
+			return -1;
+
+	if (term_get_char(&c) || c != cESC)
 		return -1;
-	c = getc();
-	if (c != '[')
+
+	if (term_get_char(&c) || c != '[')
 		return -1;
 
 	n[0] = 0;
 	while (1) {
-		c = getc();
-		if (c == ';') {
-			i++;
-			if (i >= num)
+		if (!term_get_char(&c)) {
+			if (c == ';') {
+				i++;
+				if (i >= num)
+					return -1;
+				n[i] = 0;
+				continue;
+			} else if (c == end_char) {
+				break;
+			} else if (c > '9' || c < '0') {
 				return -1;
-			n[i] = 0;
-			continue;
-		} else if (c == end_char) {
-			break;
-		} else if (c > '9' || c < '0') {
-			return -1;
+			}
+
+			/* Read one more decimal position */
+			n[i] *= 10;
+			n[i] += c - '0';
 		}
 
-		/* Read one more decimal position */
-		n[i] *= 10;
-		n[i] += c - '0';
+		if (timer_get_us() > timeout)
+			return -1;
 	}
 	if (i != num - 1)
 		return -1;
@@ -196,7 +216,6 @@ static int query_console_serial(int *rows, int *cols)
 {
 	int ret = 0;
 	int n[2];
-	u64 timeout;
 
 	/* Empty input buffer */
 	while (tstc())
@@ -216,14 +235,6 @@ static int query_console_serial(int *rows, int *cols)
 	       ESC "[999;999H"	/* Move to bottom right corner */
 	       ESC "[6n");	/* Query cursor position */
 
-	/* Allow up to one second for a response */
-	timeout = timer_get_us() + 1000000;
-	while (!tstc())
-		if (timer_get_us() > timeout) {
-			ret = -1;
-			goto out;
-		}
-
 	/* Read {rows,cols} */
 	if (term_read_reply(n, 2, 'R')) {
 		ret = 1;
-- 
2.20.1



More information about the U-Boot mailing list