Commit 5644369450635fa5c2967bee55b1ac41f6e988d0

Authored by Tom Rini

Merge branch 'agust@denx.de' of git://git.denx.de/u-boot-staging

Showing 10 changed files Side-by-side Diff

board/ait/cam_enc_4xx/cam_enc_4xx.c
... ... @@ -561,7 +561,8 @@
561 561 char *s;
562 562 char temp[6][200];
563 563  
564   - m = menu_create(display->title, display->timeout, 1, ait_menu_print);
  564 + m = menu_create(display->title, display->timeout, 1, ait_menu_print,
  565 + NULL, NULL);
565 566  
566 567 for (i = 0; display->menulist[i]; i++) {
567 568 sprintf(key, "%d", i + 1);
... ... @@ -75,6 +75,7 @@
75 75 COBJS-$(CONFIG_CMD_BDI) += cmd_bdinfo.o
76 76 COBJS-$(CONFIG_CMD_BEDBUG) += bedbug.o cmd_bedbug.o
77 77 COBJS-$(CONFIG_CMD_BMP) += cmd_bmp.o
  78 +COBJS-$(CONFIG_CMD_BOOTMENU) += cmd_bootmenu.o
78 79 COBJS-$(CONFIG_CMD_BOOTLDR) += cmd_bootldr.o
79 80 COBJS-$(CONFIG_CMD_BOOTSTAGE) += cmd_bootstage.o
80 81 COBJS-$(CONFIG_CMD_CACHE) += cmd_cache.o
common/cmd_bootmenu.c
  1 +/*
  2 + * (C) Copyright 2011-2013 Pali Rohár <pali.rohar@gmail.com>
  3 + *
  4 + * See file CREDITS for list of people who contributed to this
  5 + * project.
  6 + *
  7 + * This program is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU General Public License as
  9 + * published by the Free Software Foundation; either version 2 of
  10 + * the License, or (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  20 + * MA 02111-1307 USA
  21 + */
  22 +
  23 +#include <common.h>
  24 +#include <command.h>
  25 +#include <ansi.h>
  26 +#include <menu.h>
  27 +#include <hush.h>
  28 +#include <watchdog.h>
  29 +#include <malloc.h>
  30 +#include <linux/string.h>
  31 +
  32 +/* maximum bootmenu entries */
  33 +#define MAX_COUNT 99
  34 +
  35 +/* maximal size of bootmenu env
  36 + * 9 = strlen("bootmenu_")
  37 + * 2 = strlen(MAX_COUNT)
  38 + * 1 = NULL term
  39 + */
  40 +#define MAX_ENV_SIZE (9 + 2 + 1)
  41 +
  42 +struct bootmenu_entry {
  43 + unsigned short int num; /* unique number 0 .. MAX_COUNT */
  44 + char key[3]; /* key identifier of number */
  45 + char *title; /* title of entry */
  46 + char *command; /* hush command of entry */
  47 + struct bootmenu_data *menu; /* this bootmenu */
  48 + struct bootmenu_entry *next; /* next menu entry (num+1) */
  49 +};
  50 +
  51 +struct bootmenu_data {
  52 + int delay; /* delay for autoboot */
  53 + int active; /* active menu entry */
  54 + int count; /* total count of menu entries */
  55 + struct bootmenu_entry *first; /* first menu entry */
  56 +};
  57 +
  58 +enum bootmenu_key {
  59 + KEY_NONE = 0,
  60 + KEY_UP,
  61 + KEY_DOWN,
  62 + KEY_SELECT,
  63 +};
  64 +
  65 +static char *bootmenu_getoption(unsigned short int n)
  66 +{
  67 + char name[MAX_ENV_SIZE] = "bootmenu_";
  68 +
  69 + if (n > MAX_COUNT)
  70 + return NULL;
  71 +
  72 + sprintf(name + 9, "%d", n);
  73 + return getenv(name);
  74 +}
  75 +
  76 +static void bootmenu_print_entry(void *data)
  77 +{
  78 + struct bootmenu_entry *entry = data;
  79 + int reverse = (entry->menu->active == entry->num);
  80 +
  81 + /*
  82 + * Move cursor to line where the entry will be drown (entry->num)
  83 + * First 3 lines contain bootmenu header + 1 empty line
  84 + */
  85 + printf(ANSI_CURSOR_POSITION, entry->num + 4, 1);
  86 +
  87 + puts(" ");
  88 +
  89 + if (reverse)
  90 + puts(ANSI_COLOR_REVERSE);
  91 +
  92 + puts(entry->title);
  93 +
  94 + if (reverse)
  95 + puts(ANSI_COLOR_RESET);
  96 +}
  97 +
  98 +static void bootmenu_autoboot_loop(struct bootmenu_data *menu,
  99 + enum bootmenu_key *key, int *esc)
  100 +{
  101 + int i, c;
  102 +
  103 + if (menu->delay > 0) {
  104 + printf(ANSI_CURSOR_POSITION, menu->count + 5, 1);
  105 + printf(" Hit any key to stop autoboot: %2d ", menu->delay);
  106 + }
  107 +
  108 + while (menu->delay > 0) {
  109 + for (i = 0; i < 100; ++i) {
  110 + if (!tstc()) {
  111 + WATCHDOG_RESET();
  112 + mdelay(10);
  113 + continue;
  114 + }
  115 +
  116 + menu->delay = -1;
  117 + c = getc();
  118 +
  119 + switch (c) {
  120 + case '\e':
  121 + *esc = 1;
  122 + *key = KEY_NONE;
  123 + break;
  124 + case '\r':
  125 + *key = KEY_SELECT;
  126 + break;
  127 + default:
  128 + *key = KEY_NONE;
  129 + break;
  130 + }
  131 +
  132 + break;
  133 + }
  134 +
  135 + if (menu->delay < 0)
  136 + break;
  137 +
  138 + --menu->delay;
  139 + printf("\b\b\b%2d ", menu->delay);
  140 + }
  141 +
  142 + printf(ANSI_CURSOR_POSITION, menu->count + 5, 1);
  143 + puts(ANSI_CLEAR_LINE);
  144 +
  145 + if (menu->delay == 0)
  146 + *key = KEY_SELECT;
  147 +}
  148 +
  149 +static void bootmenu_loop(struct bootmenu_data *menu,
  150 + enum bootmenu_key *key, int *esc)
  151 +{
  152 + int c;
  153 +
  154 + while (!tstc()) {
  155 + WATCHDOG_RESET();
  156 + mdelay(10);
  157 + }
  158 +
  159 + c = getc();
  160 +
  161 + switch (*esc) {
  162 + case 0:
  163 + /* First char of ANSI escape sequence '\e' */
  164 + if (c == '\e') {
  165 + *esc = 1;
  166 + *key = KEY_NONE;
  167 + }
  168 + break;
  169 + case 1:
  170 + /* Second char of ANSI '[' */
  171 + if (c == '[') {
  172 + *esc = 2;
  173 + *key = KEY_NONE;
  174 + } else {
  175 + *esc = 0;
  176 + }
  177 + break;
  178 + case 2:
  179 + case 3:
  180 + /* Third char of ANSI (number '1') - optional */
  181 + if (*esc == 2 && c == '1') {
  182 + *esc = 3;
  183 + *key = KEY_NONE;
  184 + break;
  185 + }
  186 +
  187 + *esc = 0;
  188 +
  189 + /* ANSI 'A' - key up was pressed */
  190 + if (c == 'A')
  191 + *key = KEY_UP;
  192 + /* ANSI 'B' - key down was pressed */
  193 + else if (c == 'B')
  194 + *key = KEY_DOWN;
  195 + /* other key was pressed */
  196 + else
  197 + *key = KEY_NONE;
  198 +
  199 + break;
  200 + }
  201 +
  202 + /* enter key was pressed */
  203 + if (c == '\r')
  204 + *key = KEY_SELECT;
  205 +}
  206 +
  207 +static char *bootmenu_choice_entry(void *data)
  208 +{
  209 + struct bootmenu_data *menu = data;
  210 + struct bootmenu_entry *iter;
  211 + enum bootmenu_key key = KEY_NONE;
  212 + int esc = 0;
  213 + int i;
  214 +
  215 + while (1) {
  216 + if (menu->delay >= 0) {
  217 + /* Autoboot was not stopped */
  218 + bootmenu_autoboot_loop(menu, &key, &esc);
  219 + } else {
  220 + /* Some key was pressed, so autoboot was stopped */
  221 + bootmenu_loop(menu, &key, &esc);
  222 + }
  223 +
  224 + switch (key) {
  225 + case KEY_UP:
  226 + if (menu->active > 0)
  227 + --menu->active;
  228 + /* no menu key selected, regenerate menu */
  229 + return NULL;
  230 + case KEY_DOWN:
  231 + if (menu->active < menu->count - 1)
  232 + ++menu->active;
  233 + /* no menu key selected, regenerate menu */
  234 + return NULL;
  235 + case KEY_SELECT:
  236 + iter = menu->first;
  237 + for (i = 0; i < menu->active; ++i)
  238 + iter = iter->next;
  239 + return iter->key;
  240 + default:
  241 + break;
  242 + }
  243 + }
  244 +
  245 + /* never happens */
  246 + debug("bootmenu: this should not happen");
  247 + return NULL;
  248 +}
  249 +
  250 +static void bootmenu_destroy(struct bootmenu_data *menu)
  251 +{
  252 + struct bootmenu_entry *iter = menu->first;
  253 + struct bootmenu_entry *next;
  254 +
  255 + while (iter) {
  256 + next = iter->next;
  257 + free(iter->title);
  258 + free(iter->command);
  259 + free(iter);
  260 + iter = next;
  261 + }
  262 + free(menu);
  263 +}
  264 +
  265 +static struct bootmenu_data *bootmenu_create(int delay)
  266 +{
  267 + unsigned short int i = 0;
  268 + const char *option;
  269 + struct bootmenu_data *menu;
  270 + struct bootmenu_entry *iter = NULL;
  271 +
  272 + int len;
  273 + char *sep;
  274 + struct bootmenu_entry *entry;
  275 +
  276 + menu = malloc(sizeof(struct bootmenu_data));
  277 + if (!menu)
  278 + return NULL;
  279 +
  280 + menu->delay = delay;
  281 + menu->active = 0;
  282 + menu->first = NULL;
  283 +
  284 + while ((option = bootmenu_getoption(i))) {
  285 + sep = strchr(option, '=');
  286 + if (!sep) {
  287 + printf("Invalid bootmenu entry: %s\n", option);
  288 + break;
  289 + }
  290 +
  291 + entry = malloc(sizeof(struct bootmenu_entry));
  292 + if (!entry)
  293 + goto cleanup;
  294 +
  295 + len = sep-option;
  296 + entry->title = malloc(len + 1);
  297 + if (!entry->title) {
  298 + free(entry);
  299 + goto cleanup;
  300 + }
  301 + memcpy(entry->title, option, len);
  302 + entry->title[len] = 0;
  303 +
  304 + len = strlen(sep + 1);
  305 + entry->command = malloc(len + 1);
  306 + if (!entry->command) {
  307 + free(entry->title);
  308 + free(entry);
  309 + goto cleanup;
  310 + }
  311 + memcpy(entry->command, sep + 1, len);
  312 + entry->command[len] = 0;
  313 +
  314 + sprintf(entry->key, "%d", i);
  315 +
  316 + entry->num = i;
  317 + entry->menu = menu;
  318 + entry->next = NULL;
  319 +
  320 + if (!iter)
  321 + menu->first = entry;
  322 + else
  323 + iter->next = entry;
  324 +
  325 + iter = entry;
  326 + ++i;
  327 +
  328 + if (i == MAX_COUNT - 1)
  329 + break;
  330 + }
  331 +
  332 + /* Add U-Boot console entry at the end */
  333 + if (i <= MAX_COUNT - 1) {
  334 + entry = malloc(sizeof(struct bootmenu_entry));
  335 + if (!entry)
  336 + goto cleanup;
  337 +
  338 + entry->title = strdup("U-Boot console");
  339 + if (!entry->title) {
  340 + free(entry);
  341 + goto cleanup;
  342 + }
  343 +
  344 + entry->command = strdup("");
  345 + if (!entry->command) {
  346 + free(entry->title);
  347 + free(entry);
  348 + goto cleanup;
  349 + }
  350 +
  351 + sprintf(entry->key, "%d", i);
  352 +
  353 + entry->num = i;
  354 + entry->menu = menu;
  355 + entry->next = NULL;
  356 +
  357 + if (!iter)
  358 + menu->first = entry;
  359 + else
  360 + iter->next = entry;
  361 +
  362 + iter = entry;
  363 + ++i;
  364 + }
  365 +
  366 + menu->count = i;
  367 + return menu;
  368 +
  369 +cleanup:
  370 + bootmenu_destroy(menu);
  371 + return NULL;
  372 +}
  373 +
  374 +static void bootmenu_show(int delay)
  375 +{
  376 + int init = 0;
  377 + void *choice = NULL;
  378 + char *title = NULL;
  379 + char *command = NULL;
  380 + struct menu *menu;
  381 + struct bootmenu_data *bootmenu;
  382 + struct bootmenu_entry *iter;
  383 + char *option, *sep;
  384 +
  385 + /* If delay is 0 do not create menu, just run first entry */
  386 + if (delay == 0) {
  387 + option = bootmenu_getoption(0);
  388 + if (!option) {
  389 + puts("bootmenu option 0 was not found\n");
  390 + return;
  391 + }
  392 + sep = strchr(option, '=');
  393 + if (!sep) {
  394 + puts("bootmenu option 0 is invalid\n");
  395 + return;
  396 + }
  397 + run_command(sep+1, 0);
  398 + return;
  399 + }
  400 +
  401 + bootmenu = bootmenu_create(delay);
  402 + if (!bootmenu)
  403 + return;
  404 +
  405 + menu = menu_create(NULL, bootmenu->delay, 1, bootmenu_print_entry,
  406 + bootmenu_choice_entry, bootmenu);
  407 + if (!menu) {
  408 + bootmenu_destroy(bootmenu);
  409 + return;
  410 + }
  411 +
  412 + for (iter = bootmenu->first; iter; iter = iter->next) {
  413 + if (!menu_item_add(menu, iter->key, iter))
  414 + goto cleanup;
  415 + }
  416 +
  417 + /* Default menu entry is always first */
  418 + menu_default_set(menu, "0");
  419 +
  420 + puts(ANSI_CURSOR_HIDE);
  421 + puts(ANSI_CLEAR_CONSOLE);
  422 + printf(ANSI_CURSOR_POSITION, 1, 1);
  423 +
  424 + init = 1;
  425 +
  426 + if (menu_get_choice(menu, &choice)) {
  427 + iter = choice;
  428 + title = strdup(iter->title);
  429 + command = strdup(iter->command);
  430 + }
  431 +
  432 +cleanup:
  433 + menu_destroy(menu);
  434 + bootmenu_destroy(bootmenu);
  435 +
  436 + if (init) {
  437 + puts(ANSI_CURSOR_SHOW);
  438 + puts(ANSI_CLEAR_CONSOLE);
  439 + printf(ANSI_CURSOR_POSITION, 1, 1);
  440 + }
  441 +
  442 + if (title && command) {
  443 + debug("Starting entry '%s'\n", title);
  444 + free(title);
  445 + run_command(command, 0);
  446 + free(command);
  447 + }
  448 +
  449 +#ifdef CONFIG_POSTBOOTMENU
  450 + run_command(CONFIG_POSTBOOTMENU, 0);
  451 +#endif
  452 +}
  453 +
  454 +void menu_display_statusline(struct menu *m)
  455 +{
  456 + struct bootmenu_entry *entry;
  457 + struct bootmenu_data *menu;
  458 +
  459 + if (menu_default_choice(m, (void *)&entry) < 0)
  460 + return;
  461 +
  462 + menu = entry->menu;
  463 +
  464 + printf(ANSI_CURSOR_POSITION, 1, 1);
  465 + puts(ANSI_CLEAR_LINE);
  466 + printf(ANSI_CURSOR_POSITION, 2, 1);
  467 + puts(" *** U-Boot Boot Menu ***");
  468 + puts(ANSI_CLEAR_LINE_TO_END);
  469 + printf(ANSI_CURSOR_POSITION, 3, 1);
  470 + puts(ANSI_CLEAR_LINE);
  471 +
  472 + /* First 3 lines are bootmenu header + 2 empty lines between entries */
  473 + printf(ANSI_CURSOR_POSITION, menu->count + 5, 1);
  474 + puts(ANSI_CLEAR_LINE);
  475 + printf(ANSI_CURSOR_POSITION, menu->count + 6, 1);
  476 + puts(" Press UP/DOWN to move, ENTER to select");
  477 + puts(ANSI_CLEAR_LINE_TO_END);
  478 + printf(ANSI_CURSOR_POSITION, menu->count + 7, 1);
  479 + puts(ANSI_CLEAR_LINE);
  480 +}
  481 +
  482 +#ifdef CONFIG_MENU_SHOW
  483 +int menu_show(int bootdelay)
  484 +{
  485 + bootmenu_show(bootdelay);
  486 + return -1; /* -1 - abort boot and run monitor code */
  487 +}
  488 +#endif
  489 +
  490 +int do_bootmenu(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
  491 +{
  492 + char *delay_str = NULL;
  493 + int delay = 10;
  494 +
  495 +#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
  496 + delay = CONFIG_BOOTDELAY;
  497 +#endif
  498 +
  499 + if (argc >= 2)
  500 + delay_str = argv[1];
  501 +
  502 + if (!delay_str)
  503 + delay_str = getenv("bootmenu_delay");
  504 +
  505 + if (delay_str)
  506 + delay = (int)simple_strtol(delay_str, NULL, 10);
  507 +
  508 + bootmenu_show(delay);
  509 + return 0;
  510 +}
  511 +
  512 +U_BOOT_CMD(
  513 + bootmenu, 2, 1, do_bootmenu,
  514 + "ANSI terminal bootmenu",
  515 + "[delay]\n"
  516 + " - show ANSI terminal bootmenu with autoboot delay"
  517 +);
... ... @@ -1280,7 +1280,8 @@
1280 1280 /*
1281 1281 * Create a menu and add items for all the labels.
1282 1282 */
1283   - m = menu_create(cfg->title, cfg->timeout, cfg->prompt, label_print);
  1283 + m = menu_create(cfg->title, cfg->timeout, cfg->prompt, label_print,
  1284 + NULL, NULL);
1284 1285  
1285 1286 if (!m)
1286 1287 return NULL;
... ... @@ -47,6 +47,8 @@
47 47 char *title;
48 48 int prompt;
49 49 void (*item_data_print)(void *);
  50 + char *(*item_choice)(void *);
  51 + void *item_choice_data;
50 52 struct list_head items;
51 53 };
52 54  
... ... @@ -174,7 +176,7 @@
174 176 * Set *choice to point to the default item's data, if any default item was
175 177 * set, and returns 1. If no default item was set, returns -ENOENT.
176 178 */
177   -static inline int menu_default_choice(struct menu *m, void **choice)
  179 +int menu_default_choice(struct menu *m, void **choice)
178 180 {
179 181 if (m->default_item) {
180 182 *choice = m->default_item->data;
181 183  
182 184  
... ... @@ -204,18 +206,26 @@
204 206  
205 207 menu_display(m);
206 208  
207   - readret = readline_into_buffer("Enter choice: ", cbuf,
208   - m->timeout / 10);
  209 + if (!m->item_choice) {
  210 + readret = readline_into_buffer("Enter choice: ", cbuf,
  211 + m->timeout / 10);
209 212  
210   - if (readret >= 0) {
211   - choice_item = menu_item_by_key(m, cbuf);
212   -
213   - if (!choice_item) {
214   - printf("%s not found\n", cbuf);
215   - m->timeout = 0;
  213 + if (readret >= 0) {
  214 + choice_item = menu_item_by_key(m, cbuf);
  215 + if (!choice_item)
  216 + printf("%s not found\n", cbuf);
  217 + } else {
  218 + return menu_default_choice(m, choice);
216 219 }
217   - } else
218   - return menu_default_choice(m, choice);
  220 + } else {
  221 + char *key = m->item_choice(m->item_choice_data);
  222 +
  223 + if (key)
  224 + choice_item = menu_item_by_key(m, key);
  225 + }
  226 +
  227 + if (!choice_item)
  228 + m->timeout = 0;
219 229 }
220 230  
221 231 *choice = choice_item->data;
222 232  
... ... @@ -348,11 +358,19 @@
348 358 * what must be entered to select an item, the item_data_print function should
349 359 * make it obvious what the key for each entry is.
350 360 *
  361 + * item_choice - If not NULL, will be called when asking the user to choose an
  362 + * item. Returns a key string corresponding to the choosen item or NULL if
  363 + * no item has been selected.
  364 + *
  365 + * item_choice_data - Will be passed as the argument to the item_choice function
  366 + *
351 367 * Returns a pointer to the menu if successful, or NULL if there is
352 368 * insufficient memory available to create the menu.
353 369 */
354 370 struct menu *menu_create(char *title, int timeout, int prompt,
355   - void (*item_data_print)(void *))
  371 + void (*item_data_print)(void *),
  372 + char *(*item_choice)(void *),
  373 + void *item_choice_data)
356 374 {
357 375 struct menu *m;
358 376  
... ... @@ -365,6 +383,8 @@
365 383 m->prompt = prompt;
366 384 m->timeout = timeout;
367 385 m->item_data_print = item_data_print;
  386 + m->item_choice = item_choice;
  387 + m->item_choice_data = item_choice_data;
368 388  
369 389 if (title) {
370 390 m->title = strdup(title);
  1 +/*
  2 + * (C) Copyright 2011-2012 Pali Rohár <pali.rohar@gmail.com>
  3 + *
  4 + * See file CREDITS for list of people who contributed to this
  5 + * project.
  6 + *
  7 + * This program is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU General Public License as
  9 + * published by the Free Software Foundation; either version 2 of
  10 + * the License, or (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  20 + * MA 02111-1307 USA
  21 + */
  22 +
  23 +ANSI terminal bootmenu command
  24 +
  25 +The "bootmenu" command uses U-Boot menu interfaces and provides
  26 +a simple mechanism for creating menus with different boot items.
  27 +The cursor keys "Up" and "Down" are used for navigation through
  28 +the items. Current active menu item is highlighted and can be
  29 +selected using the "Enter" key. The selection of the highlighted
  30 +menu entry invokes an U-Boot command (or a list of commands)
  31 +associated with this menu entry.
  32 +
  33 +The "bootmenu" command interprets ANSI escape sequencies, so
  34 +an ANSI terminal is required for proper menu rendering and item
  35 +selection.
  36 +
  37 +The assembling of the menu is done via a set of environment variables
  38 +"bootmenu_<num>" and "bootmenu_delay", i.e.:
  39 +
  40 + bootmenu_delay=<delay>
  41 + bootmenu_<num>="<title>=<commands>"
  42 +
  43 + <delay> is the autoboot delay in seconds, after which the first
  44 + menu entry will be selected automatically
  45 +
  46 + <num> is the boot menu entry number, starting from zero
  47 +
  48 + <title> is the text of the menu entry shown on the console
  49 + or on the boot screen
  50 +
  51 + <commands> are commands which will be executed when a menu
  52 + entry is selected
  53 +
  54 + (title and commands are separated by first appearance of '='
  55 + character in the environment variable)
  56 +
  57 +First (optional) argument of the "bootmenu" command is a delay specifier
  58 +and it overrides the delay value defined by "bootmenu_delay" environment
  59 +variable. If the environment variable "bootmenu_delay" is not set or if
  60 +the argument of the "bootmenu" command is not specified, the default delay
  61 +will be CONFIG_BOOTDELAY. If delay is 0, no menu entries will be shown on
  62 +the console (or on the screen) and the command of the first menu entry will
  63 +be called immediately. If delay is less then 0, bootmenu will be shown and
  64 +autoboot will be disabled.
  65 +
  66 +Bootmenu always adds menu entry "U-Boot console" at the end of all menu
  67 +entries specified by environment variables. When selecting this entry
  68 +the bootmenu terminates and the usual U-Boot command prompt is presented
  69 +to the user.
  70 +
  71 +Example environment:
  72 +
  73 + setenv bootmenu_0 Boot 1. kernel=bootm 0x82000000 # Set first menu entry
  74 + setenv bootmenu_1 Boot 2. kernel=bootm 0x83000000 # Set second menu entry
  75 + setenv bootmenu_2 Reset board=reset # Set third menu entry
  76 + setenv bootmenu_3 U-Boot boot order=boot # Set fourth menu entry
  77 + bootmenu 20 # Run bootmenu with autoboot delay 20s
  78 +
  79 +
  80 +The above example will be rendered as below
  81 +(without decorating rectangle):
  82 +
  83 +┌──────────────────────────────────────────┐
  84 +│ │
  85 +│ *** U-Boot Boot Menu *** │
  86 +│ │
  87 +│ Boot 1. kernel │
  88 +│ Boot 2. kernel │
  89 +│ Reset board │
  90 +│ U-Boot boot order │
  91 +│ U-Boot console │
  92 +│ │
  93 +│ Hit any key to stop autoboot: 20 │
  94 +│ Press UP/DOWN to move, ENTER to select │
  95 +│ │
  96 +└──────────────────────────────────────────┘
  97 +
  98 +Selected menu entry will be highlighted - it will have inverted
  99 +background and text colors.
  100 +
  101 +To enable the "bootmenu" command add following definitions to the
  102 +board config file:
  103 +
  104 + #define CONFIG_CMD_BOOTMENU
  105 + #define CONFIG_MENU
  106 +
  107 +To run the bootmenu at startup add these additional definitions:
  108 +
  109 + #define CONFIG_AUTOBOOT_KEYED
  110 + #define CONFIG_BOOTDELAY 30
  111 + #define CONFIG_MENU_SHOW
  112 +
  113 +When you intend to use the bootmenu on color frame buffer console,
  114 +make sure to additionally define CONFIG_CFB_CONSOLE_ANSI in the
  115 +board config file.
... ... @@ -51,7 +51,9 @@
51 51 * menu_create() - Creates a menu handle with default settings
52 52 */
53 53 struct menu *menu_create(char *title, int timeout, int prompt,
54   - void (*item_data_print)(void *));
  54 + void (*item_data_print)(void *),
  55 + char *(*item_choice)(void *),
  56 + void *item_choice_data);
55 57  
56 58 /*
57 59 * menu_item_add() - Adds or replaces a menu item
... ... @@ -62,6 +64,11 @@
62 64 * menu_default_set() - Sets the default choice for the menu
63 65 */
64 66 int menu_default_set(struct menu *m, char *item_key);
  67 +
  68 +/*
  69 + * menu_default_choice() - Set *choice to point to the default item's data
  70 + */
  71 +int menu_default_choice(struct menu *m, void **choice);
65 72  
66 73 /*
67 74 * menu_get_choice() - Returns the user's selected menu entry, or the
  1 +/*
  2 + * (C) Copyright 2012
  3 + * Pali Rohár <pali.rohar@gmail.com>
  4 + *
  5 + * See file CREDITS for list of people who contributed to this
  6 + * project.
  7 + *
  8 + * This program is free software; you can redistribute it and/or
  9 + * modify it under the terms of the GNU General Public License as
  10 + * published by the Free Software Foundation; either version 2 of
  11 + * the License, or (at your option) any later version.
  12 + *
  13 + * This program is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16 + * GNU General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU General Public License
  19 + * along with this program; if not, write to the Free Software
  20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 + * MA 02111-1307 USA
  22 + */
  23 +
  24 +/*
  25 + * ANSI terminal
  26 + */
  27 +
  28 +#define ANSI_CURSOR_UP "\e[%dA"
  29 +#define ANSI_CURSOR_DOWN "\e[%dB"
  30 +#define ANSI_CURSOR_FORWARD "\e[%dC"
  31 +#define ANSI_CURSOR_BACK "\e[%dD"
  32 +#define ANSI_CURSOR_NEXTLINE "\e[%dE"
  33 +#define ANSI_CURSOR_PREVIOUSLINE "\e[%dF"
  34 +#define ANSI_CURSOR_COLUMN "\e[%dG"
  35 +#define ANSI_CURSOR_POSITION "\e[%d;%dH"
  36 +#define ANSI_CURSOR_SHOW "\e[?25h"
  37 +#define ANSI_CURSOR_HIDE "\e[?25l"
  38 +#define ANSI_CLEAR_CONSOLE "\e[2J"
  39 +#define ANSI_CLEAR_LINE_TO_END "\e[0K"
  40 +#define ANSI_CLEAR_LINE "\e[2K"
  41 +#define ANSI_COLOR_RESET "\e[0m"
  42 +#define ANSI_COLOR_REVERSE "\e[7m"
include/configs/nokia_rx51.h
... ... @@ -148,6 +148,7 @@
148 148 #define CONFIG_CMDLINE_EDITING /* add command line history */
149 149 #define CONFIG_AUTO_COMPLETE /* add autocompletion support */
150 150  
  151 +#define CONFIG_CMD_BOOTMENU /* ANSI terminal Boot Menu */
151 152 #define CONFIG_CMD_CLEAR /* ANSI terminal clear screen command */
152 153  
153 154 #ifdef ONENAND_SUPPORT
... ... @@ -287,8 +288,6 @@
287 288 #endif
288 289  
289 290 /* Environment information */
290   -#define CONFIG_BOOTDELAY 3
291   -
292 291 #define CONFIG_EXTRA_ENV_SETTINGS \
293 292 "mtdparts=" MTDPARTS_DEFAULT "\0" \
294 293 "usbtty=cdc_acm\0" \
295 294  
... ... @@ -360,10 +359,40 @@
360 359 "fi\0" \
361 360 "emmcboot=setenv mmcnum 1; run trymmcboot\0" \
362 361 "sdboot=setenv mmcnum 0; run trymmcboot\0" \
  362 + "menucmd=bootmenu\0" \
  363 + "bootmenu_0=Attached kernel=run attachboot\0" \
  364 + "bootmenu_1=Internal eMMC=run emmcboot\0" \
  365 + "bootmenu_2=External SD card=run sdboot\0" \
  366 + "bootmenu_3=U-Boot boot order=boot\0" \
  367 + "bootmenu_delay=30\0" \
363 368 ""
364 369  
365 370 #define CONFIG_PREBOOT \
366   - "if run slide; then true; else run attachboot; fi;" \
  371 + "setenv mmcnum 1; setenv mmcpart 1;" \
  372 + "setenv mmcscriptfile bootmenu.scr;" \
  373 + "if run switchmmc; then " \
  374 + "setenv mmcdone true;" \
  375 + "setenv mmctype fat;" \
  376 + "if run scriptload; then true; else " \
  377 + "setenv mmctype ext2;" \
  378 + "if run scriptload; then true; else " \
  379 + "setenv mmctype ext4;" \
  380 + "if run scriptload; then true; else " \
  381 + "setenv mmcdone false;" \
  382 + "fi;" \
  383 + "fi;" \
  384 + "fi;" \
  385 + "if ${mmcdone}; then " \
  386 + "run scriptboot;" \
  387 + "fi;" \
  388 + "fi;" \
  389 + "if run slide; then true; else " \
  390 + "setenv bootmenu_delay 0;" \
  391 + "setenv bootdelay 0;" \
  392 + "fi"
  393 +
  394 +#define CONFIG_POSTBOOTMENU \
  395 + "echo;" \
367 396 "echo Extra commands:;" \
368 397 "echo run sercon - Use serial port for control.;" \
369 398 "echo run usbcon - Use usbtty for control.;" \
... ... @@ -378,6 +407,11 @@
378 407 "run emmcboot;" \
379 408 "run attachboot;" \
380 409 "echo"
  410 +
  411 +#define CONFIG_BOOTDELAY 30
  412 +#define CONFIG_AUTOBOOT_KEYED
  413 +#define CONFIG_MENU
  414 +#define CONFIG_MENU_SHOW
381 415  
382 416 /*
383 417 * Miscellaneous configurable options
... ... @@ -21,12 +21,15 @@
21 21 struct menu;
22 22  
23 23 struct menu *menu_create(char *title, int timeout, int prompt,
24   - void (*item_data_print)(void *));
  24 + void (*item_data_print)(void *),
  25 + char *(*item_choice)(void *),
  26 + void *item_choice_data);
25 27 int menu_default_set(struct menu *m, char *item_key);
26 28 int menu_get_choice(struct menu *m, void **choice);
27 29 int menu_item_add(struct menu *m, char *item_key, void *item_data);
28 30 int menu_destroy(struct menu *m);
29 31 void menu_display_statusline(struct menu *m);
  32 +int menu_default_choice(struct menu *m, void **choice);
30 33  
31 34 #if defined(CONFIG_MENU_SHOW)
32 35 int menu_show(int bootdelay);