From ffedf5deeba4b9adf8fdf31a53c23946700d648f Mon Sep 17 00:00:00 2001 From: Toomas Soome Date: Sat, 10 Nov 2018 16:34:12 +0000 Subject: [PATCH] 9970 loader: fix EFI getchar() for multiple consoles Reviewed by: Jason King Reviewed by: Robert Mustacchi Approved by: Dan McDonald --- usr/src/boot/sys/boot/common/console.c | 28 ++++++++++++++++---------- usr/src/boot/sys/boot/efi/libefi/efi_console.c | 23 ++++++++++++--------- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/usr/src/boot/sys/boot/common/console.c b/usr/src/boot/sys/boot/common/console.c index 07e8aa4bc1..5693e819c9 100644 --- a/usr/src/boot/sys/boot/common/console.c +++ b/usr/src/boot/sys/boot/common/console.c @@ -1,4 +1,4 @@ -/*- +/* * Copyright (c) 1998 Michael Smith * All rights reserved. * @@ -25,7 +25,6 @@ */ #include -__FBSDID("$FreeBSD$"); #include #include @@ -115,16 +114,23 @@ cons_mode(int raw) int getchar(void) { - int cons; - int rv; + int cons; + int flags = C_PRESENTIN | C_ACTIVEIN; + int rv; - /* Loop forever polling all active consoles */ - for(;;) - for (cons = 0; consoles[cons] != NULL; cons++) - if ((consoles[cons]->c_flags & (C_PRESENTIN | C_ACTIVEIN)) == - (C_PRESENTIN | C_ACTIVEIN) && - ((rv = consoles[cons]->c_in(consoles[cons])) != -1)) - return(rv); + /* + * Loop forever polling all active consoles. Somewhat strangely, + * this code expects all ->c_in() implementations to effectively do an + * ischar() check first, returning -1 if there's not a char ready. + */ + for(;;) { + for (cons = 0; consoles[cons] != NULL; cons++) { + if ((consoles[cons]->c_flags & flags) == flags && + ((rv = consoles[cons]->c_in(consoles[cons])) != -1)) + return(rv); + } + delay(30 * 1000); /* delay 30ms */ + } } int diff --git a/usr/src/boot/sys/boot/efi/libefi/efi_console.c b/usr/src/boot/sys/boot/efi/libefi/efi_console.c index b2d458073f..4bf1944a32 100644 --- a/usr/src/boot/sys/boot/efi/libefi/efi_console.c +++ b/usr/src/boot/sys/boot/efi/libefi/efi_console.c @@ -1,4 +1,4 @@ -/*- +/* * Copyright (c) 2000 Doug Rabson * All rights reserved. * @@ -25,7 +25,6 @@ */ #include -__FBSDID("$FreeBSD$"); #include #include @@ -42,6 +41,9 @@ static SIMPLE_INPUT_INTERFACE *conin; #define MAXARGS 8 #define KEYBUFSZ 10 static unsigned keybuf[KEYBUFSZ]; /* keybuf for extended codes */ + +static int pending; + static int args[MAXARGS], argc; static int fg_c, bg_c; static UINTN curx, cury; @@ -497,7 +499,6 @@ efi_cons_getchar(struct console *cp __attribute((unused))) { EFI_INPUT_KEY key; EFI_STATUS status; - UINTN junk; int i, c; for (i = 0; i < KEYBUFSZ; i++) { @@ -508,12 +509,11 @@ efi_cons_getchar(struct console *cp __attribute((unused))) } } - /* Try to read a key stroke. We wait for one if none is pending. */ + pending = 0; + status = conin->ReadKeyStroke(conin, &key); - if (status == EFI_NOT_READY) { - BS->WaitForEvent(1, &conin->WaitForKey, &junk); - status = conin->ReadKeyStroke(conin, &key); - } + if (status == EFI_NOT_READY) + return (-1); switch (key.ScanCode) { case 0x1: /* UP */ @@ -550,8 +550,13 @@ efi_cons_poll(struct console *cp __attribute((unused))) return (1); } + if (pending) + return (1); + /* This can clear the signaled state. */ - return (BS->CheckEvent(conin->WaitForKey) == EFI_SUCCESS); + pending = BS->CheckEvent(conin->WaitForKey) == EFI_SUCCESS; + + return (pending); } /* Plain direct access to EFI OutputString(). */ -- 2.11.4.GIT