Merge tag 'rpi-next-2020.07.2' of https://gitlab.denx.de/u-boot/custodians/u-boot...
[oweals/u-boot.git] / common / cli_readline.c
index df446b8c8362e998c3279d799fd2a3adcbb10f58..1f1e28c6d85787983adb683379e3b4acbdb047c0 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * (C) Copyright 2000
  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
@@ -5,12 +6,13 @@
  * Add to readline cmdline-editing by
  * (C) Copyright 2005
  * JinHua Luo, GuangDong Linux Center, <luo.jinhua@gd-linux.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
+#include <bootretry.h>
 #include <cli.h>
+#include <command.h>
+#include <time.h>
 #include <watchdog.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -18,17 +20,8 @@ DECLARE_GLOBAL_DATA_PTR;
 static const char erase_seq[] = "\b \b";       /* erase sequence */
 static const char   tab_seq[] = "        ";    /* used to expand TABs */
 
-#ifdef CONFIG_BOOT_RETRY_TIME
-static uint64_t endtime;      /* must be set, default is instant timeout */
-static int      retry_time = -1; /* -1 so can call readline before main_loop */
-#endif
-
 char console_buffer[CONFIG_SYS_CBSIZE + 1];    /* console I/O buffer   */
 
-#ifndef CONFIG_BOOT_RETRY_MIN
-#define CONFIG_BOOT_RETRY_MIN CONFIG_BOOT_RETRY_TIME
-#endif
-
 static char *delete_char (char *buffer, char *p, int *colp, int *np, int plen)
 {
        char *s;
@@ -267,13 +260,8 @@ static int cread_line(const char *const prompt, char *buf, unsigned int *len,
                cread_add_str(buf, init_len, 1, &num, &eol_num, buf, *len);
 
        while (1) {
-#ifdef CONFIG_BOOT_RETRY_TIME
-               while (!tstc()) {       /* while no incoming data */
-                       if (retry_time >= 0 && get_ticks() > endtime)
-                               return -2;      /* timed out */
-                       WATCHDOG_RESET();
-               }
-#endif
+               if (bootretry_tstc_timeout())
+                       return -2;      /* timed out */
                if (first && timeout) {
                        uint64_t etime = endtick(timeout);
 
@@ -287,6 +275,10 @@ static int cread_line(const char *const prompt, char *buf, unsigned int *len,
 
                ichar = getcmd_getch();
 
+               /* ichar=0x0 when error occurs in U-Boot getc */
+               if (!ichar)
+                       continue;
+
                if ((ichar == '\n') || (ichar == '\r')) {
                        putc('\n');
                        break;
@@ -296,46 +288,82 @@ static int cread_line(const char *const prompt, char *buf, unsigned int *len,
                 * handle standard linux xterm esc sequences for arrow key, etc.
                 */
                if (esc_len != 0) {
+                       enum { ESC_REJECT, ESC_SAVE, ESC_CONVERTED } act = ESC_REJECT;
+
                        if (esc_len == 1) {
-                               if (ichar == '[') {
-                                       esc_save[esc_len] = ichar;
-                                       esc_len = 2;
-                               } else {
-                                       cread_add_str(esc_save, esc_len,
-                                                     insert, &num, &eol_num,
-                                                     buf, *len);
-                                       esc_len = 0;
+                               if (ichar == '[' || ichar == 'O')
+                                       act = ESC_SAVE;
+                       } else if (esc_len == 2) {
+                               switch (ichar) {
+                               case 'D':       /* <- key */
+                                       ichar = CTL_CH('b');
+                                       act = ESC_CONVERTED;
+                                       break;  /* pass off to ^B handler */
+                               case 'C':       /* -> key */
+                                       ichar = CTL_CH('f');
+                                       act = ESC_CONVERTED;
+                                       break;  /* pass off to ^F handler */
+                               case 'H':       /* Home key */
+                                       ichar = CTL_CH('a');
+                                       act = ESC_CONVERTED;
+                                       break;  /* pass off to ^A handler */
+                               case 'F':       /* End key */
+                                       ichar = CTL_CH('e');
+                                       act = ESC_CONVERTED;
+                                       break;  /* pass off to ^E handler */
+                               case 'A':       /* up arrow */
+                                       ichar = CTL_CH('p');
+                                       act = ESC_CONVERTED;
+                                       break;  /* pass off to ^P handler */
+                               case 'B':       /* down arrow */
+                                       ichar = CTL_CH('n');
+                                       act = ESC_CONVERTED;
+                                       break;  /* pass off to ^N handler */
+                               case '1':
+                               case '3':
+                               case '4':
+                               case '7':
+                               case '8':
+                                       if (esc_save[1] == '[') {
+                                               /* see if next character is ~ */
+                                               act = ESC_SAVE;
+                                       }
+                                       break;
+                               }
+                       } else if (esc_len == 3) {
+                               if (ichar == '~') {
+                                       switch (esc_save[2]) {
+                                       case '3':       /* Delete key */
+                                               ichar = CTL_CH('d');
+                                               act = ESC_CONVERTED;
+                                               break;  /* pass to ^D handler */
+                                       case '1':       /* Home key */
+                                       case '7':
+                                               ichar = CTL_CH('a');
+                                               act = ESC_CONVERTED;
+                                               break;  /* pass to ^A handler */
+                                       case '4':       /* End key */
+                                       case '8':
+                                               ichar = CTL_CH('e');
+                                               act = ESC_CONVERTED;
+                                               break;  /* pass to ^E handler */
+                                       }
                                }
-                               continue;
                        }
 
-                       switch (ichar) {
-                       case 'D':       /* <- key */
-                               ichar = CTL_CH('b');
-                               esc_len = 0;
-                               break;
-                       case 'C':       /* -> key */
-                               ichar = CTL_CH('f');
-                               esc_len = 0;
-                               break;  /* pass off to ^F handler */
-                       case 'H':       /* Home key */
-                               ichar = CTL_CH('a');
-                               esc_len = 0;
-                               break;  /* pass off to ^A handler */
-                       case 'A':       /* up arrow */
-                               ichar = CTL_CH('p');
-                               esc_len = 0;
-                               break;  /* pass off to ^P handler */
-                       case 'B':       /* down arrow */
-                               ichar = CTL_CH('n');
-                               esc_len = 0;
-                               break;  /* pass off to ^N handler */
-                       default:
+                       switch (act) {
+                       case ESC_SAVE:
+                               esc_save[esc_len++] = ichar;
+                               continue;
+                       case ESC_REJECT:
                                esc_save[esc_len++] = ichar;
                                cread_add_str(esc_save, esc_len, insert,
                                              &num, &eol_num, buf, *len);
                                esc_len = 0;
                                continue;
+                       case ESC_CONVERTED:
+                               esc_len = 0;
+                               break;
                        }
                }
 
@@ -539,21 +567,10 @@ int cli_readline_into_buffer(const char *const prompt, char *buffer,
        col = plen;
 
        for (;;) {
-#ifdef CONFIG_BOOT_RETRY_TIME
-               while (!tstc()) {       /* while no incoming data */
-                       if (retry_time >= 0 && get_ticks() > endtime)
-                               return -2;      /* timed out */
-                       WATCHDOG_RESET();
-               }
-#endif
+               if (bootretry_tstc_timeout())
+                       return -2;      /* timed out */
                WATCHDOG_RESET();       /* Trigger watchdog, if needed */
 
-#ifdef CONFIG_SHOW_ACTIVITY
-               while (!tstc()) {
-                       show_activity(0);
-                       WATCHDOG_RESET();
-               }
-#endif
                c = getc();
 
                /*
@@ -615,7 +632,7 @@ int cli_readline_into_buffer(const char *const prompt, char *buffer,
                                        puts(tab_seq + (col & 07));
                                        col += 8 - (col & 07);
                                } else {
-                                       char buf[2];
+                                       char __maybe_unused buf[2];
 
                                        /*
                                         * Echo input using puts() to force an
@@ -637,35 +654,3 @@ int cli_readline_into_buffer(const char *const prompt, char *buffer,
        }
 #endif
 }
-
-#ifdef CONFIG_BOOT_RETRY_TIME
-/***************************************************************************
- * initialize command line timeout
- */
-void init_cmd_timeout(void)
-{
-       char *s = getenv("bootretry");
-
-       if (s != NULL)
-               retry_time = (int)simple_strtol(s, NULL, 10);
-       else
-               retry_time =  CONFIG_BOOT_RETRY_TIME;
-
-       if (retry_time >= 0 && retry_time < CONFIG_BOOT_RETRY_MIN)
-               retry_time = CONFIG_BOOT_RETRY_MIN;
-}
-
-/***************************************************************************
- * reset command line timeout to retry_time seconds
- */
-void reset_cmd_timeout(void)
-{
-       endtime = endtick(retry_time);
-}
-
-void bootretry_dont_retry(void)
-{
-       retry_time = -1;
-}
-
-#endif