> * Added some ANSI escape codes definitions in common.h > * Configuration is done via env variables bootmenu_delay and > bootmenu_<num>: > > bootmenu_delay=<delay> > bootmenu_<num>="<title>=<commands>" > > (title and commands are separated by first char '=') > > <delay> is delay in seconds of autobooting first entry > <num> is boot menu entry, starting from zero > <title> is text shown in boot screen > <commands> are commands which will be executed when menu entry is > selected
Do you need this command if you already have common/menu.c? M > > * First argument of bootmenu command override bootmenu_delay env > * If env bootmenu_delay or bootmenu arg is not specified, delay is 10 > seconds * If delay is 0, no entry will be shown on screen and first will > be called * If delay is less then 0, no autoboot delay will be used > * Boot Menu will stop finding next menu entry if last was not defined > * Boot Menu always add menu entry "U-Boot console" at end of all entries > > * Example using: > > setenv bootmenu_0 Boot 1. kernel=bootm 0x82000000 # Set first menu > entry setenv bootmenu_1 Boot 2. kernel=bootm 0x83000000 # Set second menu > entry setenv bootmenu_2 Reset board=reset # Set third menu > entry setenv bootmenu_3 U-Boot boot order=boot # Set fourth menu > entry setenv bootmenu_4 # Empty string is end of all bootmenu entries > bootmenu 20 # Run bootmenu with autoboot delay 20s > > Signed-off-by: Pali Rohár <pali.ro...@gmail.com> > --- > Changes since original version: > - ANSI bootmenu command: use puts instead printf > - Merged parts of patch "Add some ANSI escape codes definitions in > common.h" > > common/Makefile | 1 + > common/cmd_bootmenu.c | 366 > ++++++++++++++++++++++++++++++++++++++++++++++ include/common.h | > 13 ++ > include/config_cmd_all.h | 1 + > 4 files changed, 381 insertions(+), 0 deletions(-) > create mode 100644 common/cmd_bootmenu.c > > diff --git a/common/Makefile b/common/Makefile > index e1efd45..7402bfb 100644 > --- a/common/Makefile > +++ b/common/Makefile > @@ -67,6 +67,7 @@ COBJS-$(CONFIG_CMD_SOURCE) += cmd_source.o > COBJS-$(CONFIG_CMD_BDI) += cmd_bdinfo.o > COBJS-$(CONFIG_CMD_BEDBUG) += bedbug.o cmd_bedbug.o > COBJS-$(CONFIG_CMD_BMP) += cmd_bmp.o > +COBJS-$(CONFIG_CMD_BOOTMENU) += cmd_bootmenu.o > COBJS-$(CONFIG_CMD_BOOTLDR) += cmd_bootldr.o > COBJS-$(CONFIG_CMD_CACHE) += cmd_cache.o > COBJS-$(CONFIG_CMD_CLEAR) += cmd_clear.o > diff --git a/common/cmd_bootmenu.c b/common/cmd_bootmenu.c > new file mode 100644 > index 0000000..931ed18 > --- /dev/null > +++ b/common/cmd_bootmenu.c > @@ -0,0 +1,366 @@ > +/* > + * (C) Copyright 2011 Pali Rohár <pali.ro...@gmail.com> > + * > + * See file CREDITS for list of people who contributed to this > + * project. > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation; either version 2 of > + * the License, or (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, > + * MA 02111-1307 USA > + */ > + > +#include <common.h> > +#include <command.h> > +#include <watchdog.h> > +#include <linux/string.h> > + > +#ifdef CONFIG_SYS_HUSH_PARSER > +#include <hush.h> > +#endif > + > +static char *get_option(int n) > +{ > + > + char name[] = "bootmenu_\0\0"; > + > + if (n < 0 || n > 99) > + return NULL; > + > + sprintf(name+9, "%d", n); > + > + return getenv(name); > + > +} > + > +static char *get_end_of_title(char *str) > +{ > + > + if (!str) > + return NULL; > + > + return strchr(str, '='); > + > +} > + > +static int print_title(char *begin, char *end) > +{ > + > + if (!begin || !end || end < begin) > + return 1; > + > + while (begin != end) > + putc(*(begin++)); > + > + return 0; > + > +} > + > +static int print_entry(int n, int reverse) > +{ > + > + char *str = get_option(n); > + char *end = get_end_of_title(str); > + > + if (!end) > + return 1; > + > + printf(ANSI_CURSOR_POSITION, n+4, 1); > + > + if (reverse) > + puts(ANSI_COLOR_REVERSE); > + > + puts(" "); > + print_title(str, end); > + puts(ANSI_CLEAR_LINE_TO_END); > + > + if (reverse) > + puts(ANSI_COLOR_RESET); > + > + return 0; > + > +} > + > +static int print_menu(int active) > +{ > + > + int n = 0; > + > + printf(ANSI_CURSOR_POSITION, 1, 1); > + puts(ANSI_CLEAR_LINE); > + printf(ANSI_CURSOR_POSITION, 2, 1); > + puts(" *** U-Boot BOOT MENU ***"); > + puts(ANSI_CLEAR_LINE_TO_END); > + printf(ANSI_CURSOR_POSITION, 3, 1); > + puts(ANSI_CLEAR_LINE); > + > + while (1) { > + > + int ret = print_entry(n, n == active ? 1 : 0); > + > + if (ret == 1) > + break; > + > + ++n; > + > + } > + > + printf(ANSI_CURSOR_POSITION, n+4, 1); > + > + if (n == active) > + puts(ANSI_COLOR_REVERSE); > + > + puts(" U-Boot console"); > + puts(ANSI_CLEAR_LINE_TO_END); > + > + if (n == active) > + puts(ANSI_COLOR_RESET); > + > + printf(ANSI_CURSOR_POSITION, n+5, 1); > + puts(ANSI_CLEAR_LINE); > + printf(ANSI_CURSOR_POSITION, n+6, 1); > + puts(" Press UP/DOWN to move, ENTER to select"); > + puts(ANSI_CLEAR_LINE_TO_END); > + printf(ANSI_CURSOR_POSITION, n+7, 1); > + puts(ANSI_CLEAR_LINE); > + > + return n; > + > +} > + > +int do_bootmenu(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) > +{ > + > + int active = 0; > + int abort = 0; > + int key = 0; /* 0 - NONE, 1 - UP, 2 - DOWN, 3 - SELECT */ > + int esc = 0; > + int count = 0; > + int delay = 10; > + int instant = 0; > + char *delay_str = NULL; > + > + if (argc >= 2) > + delay_str = argv[1]; > + > + if (!delay_str) > + delay_str = getenv("bootmenu_delay"); > + > + if (delay_str) > + delay = (int)simple_strtol(delay_str, NULL, 10); > + > + if (delay == 0) { > + > + /* prevent setting U-Boot console as first menu entry */ > + if (get_end_of_title(get_option(0))) > + count = 1; > + > + instant = 1; > + > + } > + > + if (delay < 0) > + abort = 1; > + > + if (!instant) { > + > + puts(ANSI_CURSOR_HIDE); > + puts(ANSI_CLEAR_CONSOLE); > + printf(ANSI_CURSOR_POSITION, 1, 1); > + > + } > + > + while (1) { > + > + if (abort || delay > 0) > + count = print_menu(active); > + > + if (!abort) { > + > + if (delay > 0) > + printf(" Hit any key to stop autoboot: %2d ", > + delay); > + > + while (delay > 0) { > + > + int i; > + > + for (i = 0; i < 100; ++i) { > + > + if (tstc()) { > + > + abort = 1; > + key = getc(); > + > + if (key == '\e') { > + esc = 1; > + key = 0; > + } else if (key == '\r') > + key = 3; > + else > + key = 0; > + > + break; > + > + } > + > + WATCHDOG_RESET(); > + udelay(10000); > + > + } > + > + if (abort) > + break; > + > + --delay; > + printf("\b\b\b%2d ", delay); > + > + } > + > + if (delay <= 0) > + key = 3; > + > + } else { > + > + while (!tstc()) { > + > + WATCHDOG_RESET(); > + udelay(10000); > + > + } > + > + key = getc(); > + > + if (esc == 0) { > + > + if (key == '\e') { > + esc = 1; > + key = 0; > + } > + > + } else if (esc == 1) { > + > + if (key == '[') { > + esc = 2; > + key = 0; > + } else > + esc = 0; > + > + } else if (esc == 2 || esc == 3) { > + > + if (esc == 2 && key == '1') { > + esc = 3; > + key = 0; > + } else > + esc = 0; > + > + if (key == 'A') > + key = 1; > + else if (key == 'B') > + key = 2; > + else > + key = 0; > + > + } > + > + if (key == '\r') > + key = 3; > + > + } > + > + if (key == 1) { > + > + if (active > 0) > + --active; > + > + } else if (key == 2) { > + > + if (active < count) > + ++active; > + > + } else if (key == 3) { > + > + char *str; > + char *end; > + > + putc('\n'); > + > + if (!instant) { > + > + puts(ANSI_CURSOR_SHOW); > + puts(ANSI_CLEAR_CONSOLE); > + printf(ANSI_CURSOR_POSITION, 1, 1); > + > + } > + > + WATCHDOG_RESET(); > + > + /* last entry is always U-Boot console */ > + if (active == count) { > + > + puts("Starting U-Boot console\n\n"); > + return 0; > + > + } > + > + str = get_option(active); > + end = get_end_of_title(str); > + > + if (!end) { > + > + printf("Invalid Boot Menu entry %d\n", active); > + puts("Starting U-Boot console\n\n"); > + return 0; > + > + } > + > + if (!end[1]) { > + > + printf("Invalid Boot Menu entry %d: ", active); > + print_title(str, end); > + puts("\nStarting U-Boot console\n\n"); > + return 0; > + > + } > + > + printf("Booting Boot Menu entry %d: ", active); > + print_title(str, end); > + puts(" ...\n\n"); > + > +#ifndef CONFIG_SYS_HUSH_PARSER > + run_command(end+1, 0); > +#else > + parse_string_outer(end+1, FLAG_PARSE_SEMICOLON | > + FLAG_EXIT_FROM_LOOP); > +#endif > + > + printf("\nFailed booting Boot Menu entry %d: ", active); > + print_title(str, end); > + puts("\nStarting U-Boot console\n\n"); > + return 0; > + > + } > + > + } > + > + /* never happends */ > + return 1; > + > +} > + > +U_BOOT_CMD( > + bootmenu, 2, 1, do_bootmenu, > + "ANSI terminal bootmenu", > + "[delay]\n" > + " - show ANSI terminal bootmenu with autoboot delay (default 10s)" > +); > diff --git a/include/common.h b/include/common.h > index 9c0449e..c6dd2ea 100644 > --- a/include/common.h > +++ b/include/common.h > @@ -754,8 +754,21 @@ int disable_ctrlc (int); /* 1 to disable, 0 to enable > Control-C detect */ * ANSI terminal > */ > > +#define ANSI_CURSOR_UP "\e[%dA" > +#define ANSI_CURSOR_DOWN "\e[%dB" > +#define ANSI_CURSOR_FORWARD "\e[%dC" > +#define ANSI_CURSOR_BACK "\e[%dD" > +#define ANSI_CURSOR_NEXTLINE "\e[%dE" > +#define ANSI_CURSOR_PREVIOUSLINE "\e[%dF" > +#define ANSI_CURSOR_COLUMN "\e[%dG" > #define ANSI_CURSOR_POSITION "\e[%d;%dH" > +#define ANSI_CURSOR_SHOW "\e[?25h" > +#define ANSI_CURSOR_HIDE "\e[?25l" > #define ANSI_CLEAR_CONSOLE "\e[2J" > +#define ANSI_CLEAR_LINE_TO_END "\e[0K" > +#define ANSI_CLEAR_LINE "\e[2K" > +#define ANSI_COLOR_RESET "\e[0m" > +#define ANSI_COLOR_REVERSE "\e[7m" > > /* > * STDIO based functions (can always be used) > diff --git a/include/config_cmd_all.h b/include/config_cmd_all.h > index 3f25eba..8c0a648 100644 > --- a/include/config_cmd_all.h > +++ b/include/config_cmd_all.h > @@ -20,6 +20,7 @@ > #define CONFIG_CMD_BEDBUG /* Include BedBug Debugger */ > #define CONFIG_CMD_BMP /* BMP support */ > #define CONFIG_CMD_BOOTD /* bootd */ > +#define CONFIG_CMD_BOOTMENU /* ANSI terminal Boot Menu */ > #define CONFIG_CMD_BSP /* Board Specific functions */ > #define CONFIG_CMD_CACHE /* icache, dcache */ > #define CONFIG_CMD_CDP /* Cisco Discovery Protocol */ _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot