[PATCH u-boot-marvell 06/10] tools: kwboot: Add support for backspace key in mini terminal

Stefan Roese sr at denx.de
Fri Mar 4 08:49:45 CET 2022


On 3/2/22 11:49, Pali Rohár wrote:
> Marvell BootROM recognize only '\b' byte as backspace. Use terminfo
> for retrieving current backspace sequence and replace any occurrence of
> backspace sequence by the '\b' byte.
> 
> Reading terminfo database is possible via tigetstr() function from system
> library libtinfo.so.*. So link kwboot with -ltinfo.
> 
> Normally terminfo functions are in <term.h> system header file. But this
> header file conflicts with U-Boot "termios_linux.h" header file. So declare
> terminfo functions manually.
> 
> Signed-off-by: Pali Rohár <pali at kernel.org>

Reviewed-by: Stefan Roese <sr at denx.de>
Tested-by: Stefan Roese <sr at denx.de>

Thanks,
Stefan

> ---
>   tools/Makefile |   2 +-
>   tools/kwboot.c | 109 +++++++++++++++++++++++++++++++++++++++++++------
>   2 files changed, 97 insertions(+), 14 deletions(-)
> 
> diff --git a/tools/Makefile b/tools/Makefile
> index c4a06dd9ba36..dca773b909b4 100644
> --- a/tools/Makefile
> +++ b/tools/Makefile
> @@ -200,7 +200,7 @@ hostprogs-$(CONFIG_EXYNOS5420) += mkexynosspl
>   HOSTCFLAGS_mkexynosspl.o := -pedantic
>   
>   HOSTCFLAGS_kwboot.o += -pthread
> -HOSTLDLIBS_kwboot += -pthread
> +HOSTLDLIBS_kwboot += -pthread -ltinfo
>   
>   ifdtool-objs := $(LIBFDT_OBJS) ifdtool.o
>   hostprogs-$(CONFIG_X86) += ifdtool
> diff --git a/tools/kwboot.c b/tools/kwboot.c
> index 3ab49e74bb67..26cfe6dea6a7 100644
> --- a/tools/kwboot.c
> +++ b/tools/kwboot.c
> @@ -36,6 +36,13 @@
>   #include <termios.h>
>   #endif
>   
> +/*
> + * These functions are in <term.h> header file, but this header file conflicts
> + * with "termios_linux.h" header file. So declare these functions manually.
> + */
> +extern int setupterm(const char *, int, int *);
> +extern char *tigetstr(const char *);
> +
>   /*
>    * Marvell BootROM UART Sensing
>    */
> @@ -1376,37 +1383,84 @@ kwboot_xmodem(int tty, const void *_img, size_t size, int baudrate)
>   }
>   
>   static int
> -kwboot_term_pipe(int in, int out, const char *quit, int *s)
> +kwboot_term_pipe(int in, int out, const char *quit, int *s, const char *kbs, int *k)
>   {
>   	char buf[128];
> -	ssize_t nin;
> +	ssize_t nin, noff;
>   
>   	nin = read(in, buf, sizeof(buf));
>   	if (nin <= 0)
>   		return -1;
>   
> -	if (quit) {
> +	noff = 0;
> +
> +	if (quit || kbs) {
>   		int i;
>   
>   		for (i = 0; i < nin; i++) {
> -			if (buf[i] == quit[*s]) {
> +			if ((quit || kbs) &&
> +			    (!quit || buf[i] != quit[*s]) &&
> +			    (!kbs || buf[i] != kbs[*k])) {
> +				const char *prefix;
> +				int plen;
> +
> +				if (quit && kbs) {
> +					prefix = (*s >= *k) ? quit : kbs;
> +					plen = (*s >= *k) ? *s : *k;
> +				} else if (quit) {
> +					prefix = quit;
> +					plen = *s;
> +				} else {
> +					prefix = kbs;
> +					plen = *k;
> +				}
> +
> +				if (plen > i && kwboot_write(out, prefix, plen - i) < 0)
> +					return -1;
> +			}
> +
> +			if (quit && buf[i] == quit[*s]) {
>   				(*s)++;
>   				if (!quit[*s]) {
>   					nin = (i > *s) ? (i - *s) : 0;
>   					break;
>   				}
> -			} else {
> -				if (*s > i && kwboot_write(out, quit, *s - i) < 0)
> -					return -1;
> +			} else if (quit) {
>   				*s = 0;
>   			}
> +
> +			if (kbs && buf[i] == kbs[*k]) {
> +				(*k)++;
> +				if (!kbs[*k]) {
> +					if (i > *k + noff &&
> +					    kwboot_write(out, buf + noff, i - *k - noff) < 0)
> +						return -1;
> +					/*
> +					 * Replace backspace key by '\b' (0x08)
> +					 * byte which is the only recognized
> +					 * backspace byte by Marvell BootROM.
> +					 */
> +					if (write(out, "\x08", 1) < 0)
> +						return -1;
> +					noff = i + 1;
> +					*k = 0;
> +				}
> +			} else if (kbs) {
> +				*k = 0;
> +			}
>   		}
>   
> -		if (i == nin)
> -			nin -= (nin > *s) ? *s : nin;
> +		if (i == nin) {
> +			i = 0;
> +			if (quit && i < *s)
> +				i = *s;
> +			if (kbs && i < *k)
> +				i = *k;
> +			nin -= (nin > i) ? i : nin;
> +		}
>   	}
>   
> -	if (kwboot_write(out, buf, nin) < 0)
> +	if (nin > noff && kwboot_write(out, buf + noff, nin - noff) < 0)
>   		return -1;
>   
>   	return 0;
> @@ -1415,7 +1469,8 @@ kwboot_term_pipe(int in, int out, const char *quit, int *s)
>   static int
>   kwboot_terminal(int tty)
>   {
> -	int rc, in, s;
> +	int rc, in, s, k;
> +	const char *kbs = NULL;
>   	const char *quit = "\34c";
>   	struct termios otio, tio;
>   
> @@ -1434,6 +1489,33 @@ kwboot_terminal(int tty)
>   			goto out;
>   		}
>   
> +		/*
> +		 * Get sequence for backspace key used by the current
> +		 * terminal. Every occurrence of this sequence will be
> +		 * replaced by '\b' byte which is the only recognized
> +		 * backspace byte by Marvell BootROM.
> +		 *
> +		 * Note that we cannot read this sequence from termios
> +		 * c_cc[VERASE] as VERASE is valid only when ICANON is
> +		 * set in termios c_lflag, which is not case for us.
> +		 *
> +		 * Also most terminals do not set termios c_cc[VERASE]
> +		 * as c_cc[VERASE] can specify only one-byte sequence
> +		 * and instead let applications to read (possible
> +		 * multi-byte) sequence for backspace key from "kbs"
> +		 * terminfo database based on $TERM env variable.
> +		 *
> +		 * So read "kbs" from terminfo database via tigetstr()
> +		 * call after successful setupterm(). Most terminals
> +		 * use byte 0x7F for backspace key, so replacement with
> +		 * '\b' is required.
> +		 */
> +		if (setupterm(NULL, STDOUT_FILENO, &rc) == 0) {
> +			kbs = tigetstr("kbs");
> +			if (kbs == (char *)-1)
> +				kbs = NULL;
> +		}
> +
>   		kwboot_printv("[Type Ctrl-%c + %c to quit]\r\n",
>   			      quit[0] | 0100, quit[1]);
>   	} else
> @@ -1441,6 +1523,7 @@ kwboot_terminal(int tty)
>   
>   	rc = 0;
>   	s = 0;
> +	k = 0;
>   
>   	do {
>   		fd_set rfds;
> @@ -1460,13 +1543,13 @@ kwboot_terminal(int tty)
>   			break;
>   
>   		if (FD_ISSET(tty, &rfds)) {
> -			rc = kwboot_term_pipe(tty, STDOUT_FILENO, NULL, NULL);
> +			rc = kwboot_term_pipe(tty, STDOUT_FILENO, NULL, NULL, NULL, NULL);
>   			if (rc)
>   				break;
>   		}
>   
>   		if (in >= 0 && FD_ISSET(in, &rfds)) {
> -			rc = kwboot_term_pipe(in, tty, quit, &s);
> +			rc = kwboot_term_pipe(in, tty, quit, &s, kbs, &k);
>   			if (rc)
>   				break;
>   		}

Viele Grüße,
Stefan Roese

-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-51 Fax: (+49)-8142-66989-80 Email: sr at denx.de


More information about the U-Boot mailing list