diff options
-rw-r--r-- | board/ait/cam_enc_4xx/cam_enc_4xx.c | 3 | ||||
-rw-r--r-- | common/Makefile | 1 | ||||
-rw-r--r-- | common/cmd_bootmenu.c | 517 | ||||
-rw-r--r-- | common/cmd_pxe.c | 3 | ||||
-rw-r--r-- | common/menu.c | 44 | ||||
-rw-r--r-- | doc/README.bootmenu | 115 | ||||
-rw-r--r-- | doc/README.menu | 9 | ||||
-rw-r--r-- | include/ansi.h | 42 | ||||
-rw-r--r-- | include/configs/nokia_rx51.h | 40 | ||||
-rw-r--r-- | include/menu.h | 5 |
10 files changed, 760 insertions, 19 deletions
diff --git a/board/ait/cam_enc_4xx/cam_enc_4xx.c b/board/ait/cam_enc_4xx/cam_enc_4xx.c index 32b28f9..644c445 100644 --- a/board/ait/cam_enc_4xx/cam_enc_4xx.c +++ b/board/ait/cam_enc_4xx/cam_enc_4xx.c @@ -561,7 +561,8 @@ static char *menu_handle(struct menu_display *display) char *s; char temp[6][200]; - m = menu_create(display->title, display->timeout, 1, ait_menu_print); + m = menu_create(display->title, display->timeout, 1, ait_menu_print, + NULL, NULL); for (i = 0; display->menulist[i]; i++) { sprintf(key, "%d", i + 1); diff --git a/common/Makefile b/common/Makefile index 1abf4ea..f631311 100644 --- a/common/Makefile +++ b/common/Makefile @@ -75,6 +75,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_BOOTSTAGE) += cmd_bootstage.o COBJS-$(CONFIG_CMD_CACHE) += cmd_cache.o diff --git a/common/cmd_bootmenu.c b/common/cmd_bootmenu.c new file mode 100644 index 0000000..a3cbffa --- /dev/null +++ b/common/cmd_bootmenu.c @@ -0,0 +1,517 @@ +/* + * (C) Copyright 2011-2013 Pali Rohár <pali.rohar@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 <ansi.h> +#include <menu.h> +#include <hush.h> +#include <watchdog.h> +#include <malloc.h> +#include <linux/string.h> + +/* maximum bootmenu entries */ +#define MAX_COUNT 99 + +/* maximal size of bootmenu env + * 9 = strlen("bootmenu_") + * 2 = strlen(MAX_COUNT) + * 1 = NULL term + */ +#define MAX_ENV_SIZE (9 + 2 + 1) + +struct bootmenu_entry { + unsigned short int num; /* unique number 0 .. MAX_COUNT */ + char key[3]; /* key identifier of number */ + char *title; /* title of entry */ + char *command; /* hush command of entry */ + struct bootmenu_data *menu; /* this bootmenu */ + struct bootmenu_entry *next; /* next menu entry (num+1) */ +}; + +struct bootmenu_data { + int delay; /* delay for autoboot */ + int active; /* active menu entry */ + int count; /* total count of menu entries */ + struct bootmenu_entry *first; /* first menu entry */ +}; + +enum bootmenu_key { + KEY_NONE = 0, + KEY_UP, + KEY_DOWN, + KEY_SELECT, +}; + +static char *bootmenu_getoption(unsigned short int n) +{ + char name[MAX_ENV_SIZE] = "bootmenu_"; + + if (n > MAX_COUNT) + return NULL; + + sprintf(name + 9, "%d", n); + return getenv(name); +} + +static void bootmenu_print_entry(void *data) +{ + struct bootmenu_entry *entry = data; + int reverse = (entry->menu->active == entry->num); + + /* + * Move cursor to line where the entry will be drown (entry->num) + * First 3 lines contain bootmenu header + 1 empty line + */ + printf(ANSI_CURSOR_POSITION, entry->num + 4, 1); + + puts(" "); + + if (reverse) + puts(ANSI_COLOR_REVERSE); + + puts(entry->title); + + if (reverse) + puts(ANSI_COLOR_RESET); +} + +static void bootmenu_autoboot_loop(struct bootmenu_data *menu, + enum bootmenu_key *key, int *esc) +{ + int i, c; + + if (menu->delay > 0) { + printf(ANSI_CURSOR_POSITION, menu->count + 5, 1); + printf(" Hit any key to stop autoboot: %2d ", menu->delay); + } + + while (menu->delay > 0) { + for (i = 0; i < 100; ++i) { + if (!tstc()) { + WATCHDOG_RESET(); + mdelay(10); + continue; + } + + menu->delay = -1; + c = getc(); + + switch (c) { + case '\e': + *esc = 1; + *key = KEY_NONE; + break; + case '\r': + *key = KEY_SELECT; + break; + default: + *key = KEY_NONE; + break; + } + + break; + } + + if (menu->delay < 0) + break; + + --menu->delay; + printf("\b\b\b%2d ", menu->delay); + } + + printf(ANSI_CURSOR_POSITION, menu->count + 5, 1); + puts(ANSI_CLEAR_LINE); + + if (menu->delay == 0) + *key = KEY_SELECT; +} + +static void bootmenu_loop(struct bootmenu_data *menu, + enum bootmenu_key *key, int *esc) +{ + int c; + + while (!tstc()) { + WATCHDOG_RESET(); + mdelay(10); + } + + c = getc(); + + switch (*esc) { + case 0: + /* First char of ANSI escape sequence '\e' */ + if (c == '\e') { + *esc = 1; + *key = KEY_NONE; + } + break; + case 1: + /* Second char of ANSI '[' */ + if (c == '[') { + *esc = 2; + *key = KEY_NONE; + } else { + *esc = 0; + } + break; + case 2: + case 3: + /* Third char of ANSI (number '1') - optional */ + if (*esc == 2 && c == '1') { + *esc = 3; + *key = KEY_NONE; + break; + } + + *esc = 0; + + /* ANSI 'A' - key up was pressed */ + if (c == 'A') + *key = KEY_UP; + /* ANSI 'B' - key down was pressed */ + else if (c == 'B') + *key = KEY_DOWN; + /* other key was pressed */ + else + *key = KEY_NONE; + + break; + } + + /* enter key was pressed */ + if (c == '\r') + *key = KEY_SELECT; +} + +static char *bootmenu_choice_entry(void *data) +{ + struct bootmenu_data *menu = data; + struct bootmenu_entry *iter; + enum bootmenu_key key = KEY_NONE; + int esc = 0; + int i; + + while (1) { + if (menu->delay >= 0) { + /* Autoboot was not stopped */ + bootmenu_autoboot_loop(menu, &key, &esc); + } else { + /* Some key was pressed, so autoboot was stopped */ + bootmenu_loop(menu, &key, &esc); + } + + switch (key) { + case KEY_UP: + if (menu->active > 0) + --menu->active; + /* no menu key selected, regenerate menu */ + return NULL; + case KEY_DOWN: + if (menu->active < menu->count - 1) + ++menu->active; + /* no menu key selected, regenerate menu */ + return NULL; + case KEY_SELECT: + iter = menu->first; + for (i = 0; i < menu->active; ++i) + iter = iter->next; + return iter->key; + default: + break; + } + } + + /* never happens */ + debug("bootmenu: this should not happen"); + return NULL; +} + +static void bootmenu_destroy(struct bootmenu_data *menu) +{ + struct bootmenu_entry *iter = menu->first; + struct bootmenu_entry *next; + + while (iter) { + next = iter->next; + free(iter->title); + free(iter->command); + free(iter); + iter = next; + } + free(menu); +} + +static struct bootmenu_data *bootmenu_create(int delay) +{ + unsigned short int i = 0; + const char *option; + struct bootmenu_data *menu; + struct bootmenu_entry *iter = NULL; + + int len; + char *sep; + struct bootmenu_entry *entry; + + menu = malloc(sizeof(struct bootmenu_data)); + if (!menu) + return NULL; + + menu->delay = delay; + menu->active = 0; + menu->first = NULL; + + while ((option = bootmenu_getoption(i))) { + sep = strchr(option, '='); + if (!sep) { + printf("Invalid bootmenu entry: %s\n", option); + break; + } + + entry = malloc(sizeof(struct bootmenu_entry)); + if (!entry) + goto cleanup; + + len = sep-option; + entry->title = malloc(len + 1); + if (!entry->title) { + free(entry); + goto cleanup; + } + memcpy(entry->title, option, len); + entry->title[len] = 0; + + len = strlen(sep + 1); + entry->command = malloc(len + 1); + if (!entry->command) { + free(entry->title); + free(entry); + goto cleanup; + } + memcpy(entry->command, sep + 1, len); + entry->command[len] = 0; + + sprintf(entry->key, "%d", i); + + entry->num = i; + entry->menu = menu; + entry->next = NULL; + + if (!iter) + menu->first = entry; + else + iter->next = entry; + + iter = entry; + ++i; + + if (i == MAX_COUNT - 1) + break; + } + + /* Add U-Boot console entry at the end */ + if (i <= MAX_COUNT - 1) { + entry = malloc(sizeof(struct bootmenu_entry)); + if (!entry) + goto cleanup; + + entry->title = strdup("U-Boot console"); + if (!entry->title) { + free(entry); + goto cleanup; + } + + entry->command = strdup(""); + if (!entry->command) { + free(entry->title); + free(entry); + goto cleanup; + } + + sprintf(entry->key, "%d", i); + + entry->num = i; + entry->menu = menu; + entry->next = NULL; + + if (!iter) + menu->first = entry; + else + iter->next = entry; + + iter = entry; + ++i; + } + + menu->count = i; + return menu; + +cleanup: + bootmenu_destroy(menu); + return NULL; +} + +static void bootmenu_show(int delay) +{ + int init = 0; + void *choice = NULL; + char *title = NULL; + char *command = NULL; + struct menu *menu; + struct bootmenu_data *bootmenu; + struct bootmenu_entry *iter; + char *option, *sep; + + /* If delay is 0 do not create menu, just run first entry */ + if (delay == 0) { + option = bootmenu_getoption(0); + if (!option) { + puts("bootmenu option 0 was not found\n"); + return; + } + sep = strchr(option, '='); + if (!sep) { + puts("bootmenu option 0 is invalid\n"); + return; + } + run_command(sep+1, 0); + return; + } + + bootmenu = bootmenu_create(delay); + if (!bootmenu) + return; + + menu = menu_create(NULL, bootmenu->delay, 1, bootmenu_print_entry, + bootmenu_choice_entry, bootmenu); + if (!menu) { + bootmenu_destroy(bootmenu); + return; + } + + for (iter = bootmenu->first; iter; iter = iter->next) { + if (!menu_item_add(menu, iter->key, iter)) + goto cleanup; + } + + /* Default menu entry is always first */ + menu_default_set(menu, "0"); + + puts(ANSI_CURSOR_HIDE); + puts(ANSI_CLEAR_CONSOLE); + printf(ANSI_CURSOR_POSITION, 1, 1); + + init = 1; + + if (menu_get_choice(menu, &choice)) { + iter = choice; + title = strdup(iter->title); + command = strdup(iter->command); + } + +cleanup: + menu_destroy(menu); + bootmenu_destroy(bootmenu); + + if (init) { + puts(ANSI_CURSOR_SHOW); + puts(ANSI_CLEAR_CONSOLE); + printf(ANSI_CURSOR_POSITION, 1, 1); + } + + if (title && command) { + debug("Starting entry '%s'\n", title); + free(title); + run_command(command, 0); + free(command); + } + +#ifdef CONFIG_POSTBOOTMENU + run_command(CONFIG_POSTBOOTMENU, 0); +#endif +} + +void menu_display_statusline(struct menu *m) +{ + struct bootmenu_entry *entry; + struct bootmenu_data *menu; + + if (menu_default_choice(m, (void *)&entry) < 0) + return; + + menu = entry->menu; + + 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); + + /* First 3 lines are bootmenu header + 2 empty lines between entries */ + printf(ANSI_CURSOR_POSITION, menu->count + 5, 1); + puts(ANSI_CLEAR_LINE); + printf(ANSI_CURSOR_POSITION, menu->count + 6, 1); + puts(" Press UP/DOWN to move, ENTER to select"); + puts(ANSI_CLEAR_LINE_TO_END); + printf(ANSI_CURSOR_POSITION, menu->count + 7, 1); + puts(ANSI_CLEAR_LINE); +} + +#ifdef CONFIG_MENU_SHOW +int menu_show(int bootdelay) +{ + bootmenu_show(bootdelay); + return -1; /* -1 - abort boot and run monitor code */ +} +#endif + +int do_bootmenu(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + char *delay_str = NULL; + int delay = 10; + +#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) + delay = CONFIG_BOOTDELAY; +#endif + + 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); + + bootmenu_show(delay); + return 0; +} + +U_BOOT_CMD( + bootmenu, 2, 1, do_bootmenu, + "ANSI terminal bootmenu", + "[delay]\n" + " - show ANSI terminal bootmenu with autoboot delay" +); diff --git a/common/cmd_pxe.c b/common/cmd_pxe.c index ee75db9..2dbd49c 100644 --- a/common/cmd_pxe.c +++ b/common/cmd_pxe.c @@ -1280,7 +1280,8 @@ static struct menu *pxe_menu_to_menu(struct pxe_menu *cfg) /* * Create a menu and add items for all the labels. */ - m = menu_create(cfg->title, cfg->timeout, cfg->prompt, label_print); + m = menu_create(cfg->title, cfg->timeout, cfg->prompt, label_print, + NULL, NULL); if (!m) return NULL; diff --git a/common/menu.c b/common/menu.c index 6b2a2db..64b461a 100644 --- a/common/menu.c +++ b/common/menu.c @@ -47,6 +47,8 @@ struct menu { char *title; int prompt; void (*item_data_print)(void *); + char *(*item_choice)(void *); + void *item_choice_data; struct list_head items; }; @@ -174,7 +176,7 @@ static inline struct menu_item *menu_item_by_key(struct menu *m, * Set *choice to point to the default item's data, if any default item was * set, and returns 1. If no default item was set, returns -ENOENT. */ -static inline int menu_default_choice(struct menu *m, void **choice) +int menu_default_choice(struct menu *m, void **choice) { if (m->default_item) { *choice = m->default_item->data; @@ -204,18 +206,26 @@ static inline int menu_interactive_choice(struct menu *m, void **choice) menu_display(m); - readret = readline_into_buffer("Enter choice: ", cbuf, - m->timeout / 10); + if (!m->item_choice) { + readret = readline_into_buffer("Enter choice: ", cbuf, + m->timeout / 10); - if (readret >= 0) { - choice_item = menu_item_by_key(m, cbuf); - - if (!choice_item) { - printf("%s not found\n", cbuf); - m->timeout = 0; + if (readret >= 0) { + choice_item = menu_item_by_key(m, cbuf); + if (!choice_item) + printf("%s not found\n", cbuf); + } else { + return menu_default_choice(m, choice); } - } else - return menu_default_choice(m, choice); + } else { + char *key = m->item_choice(m->item_choice_data); + + if (key) + choice_item = menu_item_by_key(m, key); + } + + if (!choice_item) + m->timeout = 0; } *choice = choice_item->data; @@ -348,11 +358,19 @@ int menu_item_add(struct menu *m, char *item_key, void *item_data) * what must be entered to select an item, the item_data_print function should * make it obvious what the key for each entry is. * + * item_choice - If not NULL, will be called when asking the user to choose an + * item. Returns a key string corresponding to the choosen item or NULL if + * no item has been selected. + * + * item_choice_data - Will be passed as the argument to the item_choice function + * * Returns a pointer to the menu if successful, or NULL if there is * insufficient memory available to create the menu. */ struct menu *menu_create(char *title, int timeout, int prompt, - void (*item_data_print)(void *)) + void (*item_data_print)(void *), + char *(*item_choice)(void *), + void *item_choice_data) { struct menu *m; @@ -365,6 +383,8 @@ struct menu *menu_create(char *title, int timeout, int prompt, m->prompt = prompt; m->timeout = timeout; m->item_data_print = item_data_print; + m->item_choice = item_choice; + m->item_choice_data = item_choice_data; if (title) { m->title = strdup(title); diff --git a/doc/README.bootmenu b/doc/README.bootmenu new file mode 100644 index 0000000..9e85b40 --- /dev/null +++ b/doc/README.bootmenu @@ -0,0 +1,115 @@ +/* + * (C) Copyright 2011-2012 Pali Rohár <pali.rohar@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 + */ + +ANSI terminal bootmenu command + +The "bootmenu" command uses U-Boot menu interfaces and provides +a simple mechanism for creating menus with different boot items. +The cursor keys "Up" and "Down" are used for navigation through +the items. Current active menu item is highlighted and can be +selected using the "Enter" key. The selection of the highlighted +menu entry invokes an U-Boot command (or a list of commands) +associated with this menu entry. + +The "bootmenu" command interprets ANSI escape sequencies, so +an ANSI terminal is required for proper menu rendering and item +selection. + +The assembling of the menu is done via a set of environment variables +"bootmenu_<num>" and "bootmenu_delay", i.e.: + + bootmenu_delay=<delay> + bootmenu_<num>="<title>=<commands>" + + <delay> is the autoboot delay in seconds, after which the first + menu entry will be selected automatically + + <num> is the boot menu entry number, starting from zero + + <title> is the text of the menu entry shown on the console + or on the boot screen + + <commands> are commands which will be executed when a menu + entry is selected + + (title and commands are separated by first appearance of '=' + character in the environment variable) + +First (optional) argument of the "bootmenu" command is a delay specifier +and it overrides the delay value defined by "bootmenu_delay" environment +variable. If the environment variable "bootmenu_delay" is not set or if +the argument of the "bootmenu" command is not specified, the default delay +will be CONFIG_BOOTDELAY. If delay is 0, no menu entries will be shown on +the console (or on the screen) and the command of the first menu entry will +be called immediately. If delay is less then 0, bootmenu will be shown and +autoboot will be disabled. + +Bootmenu always adds menu entry "U-Boot console" at the end of all menu +entries specified by environment variables. When selecting this entry +the bootmenu terminates and the usual U-Boot command prompt is presented +to the user. + +Example environment: + + 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 + bootmenu 20 # Run bootmenu with autoboot delay 20s + + +The above example will be rendered as below +(without decorating rectangle): + +┌──────────────────────────────────────────┐ +│ │ +│ *** U-Boot Boot Menu *** │ +│ │ +│ Boot 1. kernel │ +│ Boot 2. kernel │ +│ Reset board │ +│ U-Boot boot order │ +│ U-Boot console │ +│ │ +│ Hit any key to stop autoboot: 20 │ +│ Press UP/DOWN to move, ENTER to select │ +│ │ +└──────────────────────────────────────────┘ + +Selected menu entry will be highlighted - it will have inverted +background and text colors. + +To enable the "bootmenu" command add following definitions to the +board config file: + + #define CONFIG_CMD_BOOTMENU + #define CONFIG_MENU + +To run the bootmenu at startup add these additional definitions: + + #define CONFIG_AUTOBOOT_KEYED + #define CONFIG_BOOTDELAY 30 + #define CONFIG_MENU_SHOW + +When you intend to use the bootmenu on color frame buffer console, +make sure to additionally define CONFIG_CFB_CONSOLE_ANSI in the +board config file. diff --git a/doc/README.menu b/doc/README.menu index 6ce6bba..a8999ca 100644 --- a/doc/README.menu +++ b/doc/README.menu @@ -51,7 +51,9 @@ struct menu; * menu_create() - Creates a menu handle with default settings */ struct menu *menu_create(char *title, int timeout, int prompt, - void (*item_data_print)(void *)); + void (*item_data_print)(void *), + char *(*item_choice)(void *), + void *item_choice_data); /* * menu_item_add() - Adds or replaces a menu item @@ -64,6 +66,11 @@ int menu_item_add(struct menu *m, char *item_key, void *item_data); int menu_default_set(struct menu *m, char *item_key); /* + * menu_default_choice() - Set *choice to point to the default item's data + */ +int menu_default_choice(struct menu *m, void **choice); + +/* * menu_get_choice() - Returns the user's selected menu entry, or the * default if the menu is set to not prompt or the timeout expires. */ diff --git a/include/ansi.h b/include/ansi.h new file mode 100644 index 0000000..0e40b1d --- /dev/null +++ b/include/ansi.h @@ -0,0 +1,42 @@ +/* + * (C) Copyright 2012 + * Pali Rohár <pali.rohar@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 + */ + +/* + * 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" diff --git a/include/configs/nokia_rx51.h b/include/configs/nokia_rx51.h index 8506604..965330a 100644 --- a/include/configs/nokia_rx51.h +++ b/include/configs/nokia_rx51.h @@ -148,6 +148,7 @@ #define CONFIG_CMDLINE_EDITING /* add command line history */ #define CONFIG_AUTO_COMPLETE /* add autocompletion support */ +#define CONFIG_CMD_BOOTMENU /* ANSI terminal Boot Menu */ #define CONFIG_CMD_CLEAR /* ANSI terminal clear screen command */ #ifdef ONENAND_SUPPORT @@ -287,8 +288,6 @@ int rx51_kp_getc(void); #endif /* Environment information */ -#define CONFIG_BOOTDELAY 3 - #define CONFIG_EXTRA_ENV_SETTINGS \ "mtdparts=" MTDPARTS_DEFAULT "\0" \ "usbtty=cdc_acm\0" \ @@ -360,10 +359,40 @@ int rx51_kp_getc(void); "fi\0" \ "emmcboot=setenv mmcnum 1; run trymmcboot\0" \ "sdboot=setenv mmcnum 0; run trymmcboot\0" \ + "menucmd=bootmenu\0" \ + "bootmenu_0=Attached kernel=run attachboot\0" \ + "bootmenu_1=Internal eMMC=run emmcboot\0" \ + "bootmenu_2=External SD card=run sdboot\0" \ + "bootmenu_3=U-Boot boot order=boot\0" \ + "bootmenu_delay=30\0" \ "" #define CONFIG_PREBOOT \ - "if run slide; then true; else run attachboot; fi;" \ + "setenv mmcnum 1; setenv mmcpart 1;" \ + "setenv mmcscriptfile bootmenu.scr;" \ + "if run switchmmc; then " \ + "setenv mmcdone true;" \ + "setenv mmctype fat;" \ + "if run scriptload; then true; else " \ + "setenv mmctype ext2;" \ + "if run scriptload; then true; else " \ + "setenv mmctype ext4;" \ + "if run scriptload; then true; else " \ + "setenv mmcdone false;" \ + "fi;" \ + "fi;" \ + "fi;" \ + "if ${mmcdone}; then " \ + "run scriptboot;" \ + "fi;" \ + "fi;" \ + "if run slide; then true; else " \ + "setenv bootmenu_delay 0;" \ + "setenv bootdelay 0;" \ + "fi" + +#define CONFIG_POSTBOOTMENU \ + "echo;" \ "echo Extra commands:;" \ "echo run sercon - Use serial port for control.;" \ "echo run usbcon - Use usbtty for control.;" \ @@ -379,6 +408,11 @@ int rx51_kp_getc(void); "run attachboot;" \ "echo" +#define CONFIG_BOOTDELAY 30 +#define CONFIG_AUTOBOOT_KEYED +#define CONFIG_MENU +#define CONFIG_MENU_SHOW + /* * Miscellaneous configurable options */ diff --git a/include/menu.h b/include/menu.h index 7af5fdb..d8200ee 100644 --- a/include/menu.h +++ b/include/menu.h @@ -21,12 +21,15 @@ struct menu; struct menu *menu_create(char *title, int timeout, int prompt, - void (*item_data_print)(void *)); + void (*item_data_print)(void *), + char *(*item_choice)(void *), + void *item_choice_data); int menu_default_set(struct menu *m, char *item_key); int menu_get_choice(struct menu *m, void **choice); int menu_item_add(struct menu *m, char *item_key, void *item_data); int menu_destroy(struct menu *m); void menu_display_statusline(struct menu *m); +int menu_default_choice(struct menu *m, void **choice); #if defined(CONFIG_MENU_SHOW) int menu_show(int bootdelay); |