183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+ 22e192b24SSimon Glass /* 32e192b24SSimon Glass * (C) Copyright 2011-2013 Pali Rohár <pali.rohar@gmail.com> 42e192b24SSimon Glass */ 52e192b24SSimon Glass 62e192b24SSimon Glass #include <common.h> 72e192b24SSimon Glass #include <command.h> 82e192b24SSimon Glass #include <ansi.h> 92e192b24SSimon Glass #include <menu.h> 102e192b24SSimon Glass #include <watchdog.h> 112e192b24SSimon Glass #include <malloc.h> 122e192b24SSimon Glass #include <linux/string.h> 132e192b24SSimon Glass 142e192b24SSimon Glass /* maximum bootmenu entries */ 152e192b24SSimon Glass #define MAX_COUNT 99 162e192b24SSimon Glass 172e192b24SSimon Glass /* maximal size of bootmenu env 182e192b24SSimon Glass * 9 = strlen("bootmenu_") 192e192b24SSimon Glass * 2 = strlen(MAX_COUNT) 202e192b24SSimon Glass * 1 = NULL term 212e192b24SSimon Glass */ 222e192b24SSimon Glass #define MAX_ENV_SIZE (9 + 2 + 1) 232e192b24SSimon Glass 242e192b24SSimon Glass struct bootmenu_entry { 252e192b24SSimon Glass unsigned short int num; /* unique number 0 .. MAX_COUNT */ 262e192b24SSimon Glass char key[3]; /* key identifier of number */ 272e192b24SSimon Glass char *title; /* title of entry */ 282e192b24SSimon Glass char *command; /* hush command of entry */ 292e192b24SSimon Glass struct bootmenu_data *menu; /* this bootmenu */ 302e192b24SSimon Glass struct bootmenu_entry *next; /* next menu entry (num+1) */ 312e192b24SSimon Glass }; 322e192b24SSimon Glass 332e192b24SSimon Glass struct bootmenu_data { 342e192b24SSimon Glass int delay; /* delay for autoboot */ 352e192b24SSimon Glass int active; /* active menu entry */ 362e192b24SSimon Glass int count; /* total count of menu entries */ 372e192b24SSimon Glass struct bootmenu_entry *first; /* first menu entry */ 382e192b24SSimon Glass }; 392e192b24SSimon Glass 402e192b24SSimon Glass enum bootmenu_key { 412e192b24SSimon Glass KEY_NONE = 0, 422e192b24SSimon Glass KEY_UP, 432e192b24SSimon Glass KEY_DOWN, 442e192b24SSimon Glass KEY_SELECT, 452e192b24SSimon Glass }; 462e192b24SSimon Glass 472e192b24SSimon Glass static char *bootmenu_getoption(unsigned short int n) 482e192b24SSimon Glass { 492e192b24SSimon Glass char name[MAX_ENV_SIZE]; 502e192b24SSimon Glass 512e192b24SSimon Glass if (n > MAX_COUNT) 522e192b24SSimon Glass return NULL; 532e192b24SSimon Glass 542e192b24SSimon Glass sprintf(name, "bootmenu_%d", n); 5500caae6dSSimon Glass return env_get(name); 562e192b24SSimon Glass } 572e192b24SSimon Glass 582e192b24SSimon Glass static void bootmenu_print_entry(void *data) 592e192b24SSimon Glass { 602e192b24SSimon Glass struct bootmenu_entry *entry = data; 612e192b24SSimon Glass int reverse = (entry->menu->active == entry->num); 622e192b24SSimon Glass 632e192b24SSimon Glass /* 642e192b24SSimon Glass * Move cursor to line where the entry will be drown (entry->num) 652e192b24SSimon Glass * First 3 lines contain bootmenu header + 1 empty line 662e192b24SSimon Glass */ 672e192b24SSimon Glass printf(ANSI_CURSOR_POSITION, entry->num + 4, 1); 682e192b24SSimon Glass 692e192b24SSimon Glass puts(" "); 702e192b24SSimon Glass 712e192b24SSimon Glass if (reverse) 722e192b24SSimon Glass puts(ANSI_COLOR_REVERSE); 732e192b24SSimon Glass 742e192b24SSimon Glass puts(entry->title); 752e192b24SSimon Glass 762e192b24SSimon Glass if (reverse) 772e192b24SSimon Glass puts(ANSI_COLOR_RESET); 782e192b24SSimon Glass } 792e192b24SSimon Glass 802e192b24SSimon Glass static void bootmenu_autoboot_loop(struct bootmenu_data *menu, 812e192b24SSimon Glass enum bootmenu_key *key, int *esc) 822e192b24SSimon Glass { 832e192b24SSimon Glass int i, c; 842e192b24SSimon Glass 852e192b24SSimon Glass if (menu->delay > 0) { 862e192b24SSimon Glass printf(ANSI_CURSOR_POSITION, menu->count + 5, 1); 872e192b24SSimon Glass printf(" Hit any key to stop autoboot: %2d ", menu->delay); 882e192b24SSimon Glass } 892e192b24SSimon Glass 902e192b24SSimon Glass while (menu->delay > 0) { 912e192b24SSimon Glass for (i = 0; i < 100; ++i) { 922e192b24SSimon Glass if (!tstc()) { 932e192b24SSimon Glass WATCHDOG_RESET(); 942e192b24SSimon Glass mdelay(10); 952e192b24SSimon Glass continue; 962e192b24SSimon Glass } 972e192b24SSimon Glass 982e192b24SSimon Glass menu->delay = -1; 992e192b24SSimon Glass c = getc(); 1002e192b24SSimon Glass 1012e192b24SSimon Glass switch (c) { 1022e192b24SSimon Glass case '\e': 1032e192b24SSimon Glass *esc = 1; 1042e192b24SSimon Glass *key = KEY_NONE; 1052e192b24SSimon Glass break; 1062e192b24SSimon Glass case '\r': 1072e192b24SSimon Glass *key = KEY_SELECT; 1082e192b24SSimon Glass break; 1092e192b24SSimon Glass default: 1102e192b24SSimon Glass *key = KEY_NONE; 1112e192b24SSimon Glass break; 1122e192b24SSimon Glass } 1132e192b24SSimon Glass 1142e192b24SSimon Glass break; 1152e192b24SSimon Glass } 1162e192b24SSimon Glass 1172e192b24SSimon Glass if (menu->delay < 0) 1182e192b24SSimon Glass break; 1192e192b24SSimon Glass 1202e192b24SSimon Glass --menu->delay; 1212e192b24SSimon Glass printf("\b\b\b%2d ", menu->delay); 1222e192b24SSimon Glass } 1232e192b24SSimon Glass 1242e192b24SSimon Glass printf(ANSI_CURSOR_POSITION, menu->count + 5, 1); 1252e192b24SSimon Glass puts(ANSI_CLEAR_LINE); 1262e192b24SSimon Glass 1272e192b24SSimon Glass if (menu->delay == 0) 1282e192b24SSimon Glass *key = KEY_SELECT; 1292e192b24SSimon Glass } 1302e192b24SSimon Glass 1312e192b24SSimon Glass static void bootmenu_loop(struct bootmenu_data *menu, 1322e192b24SSimon Glass enum bootmenu_key *key, int *esc) 1332e192b24SSimon Glass { 1342e192b24SSimon Glass int c; 1352e192b24SSimon Glass 1362e192b24SSimon Glass while (!tstc()) { 1372e192b24SSimon Glass WATCHDOG_RESET(); 1382e192b24SSimon Glass mdelay(10); 1392e192b24SSimon Glass } 1402e192b24SSimon Glass 1412e192b24SSimon Glass c = getc(); 1422e192b24SSimon Glass 1432e192b24SSimon Glass switch (*esc) { 1442e192b24SSimon Glass case 0: 1452e192b24SSimon Glass /* First char of ANSI escape sequence '\e' */ 1462e192b24SSimon Glass if (c == '\e') { 1472e192b24SSimon Glass *esc = 1; 1482e192b24SSimon Glass *key = KEY_NONE; 1492e192b24SSimon Glass } 1502e192b24SSimon Glass break; 1512e192b24SSimon Glass case 1: 1522e192b24SSimon Glass /* Second char of ANSI '[' */ 1532e192b24SSimon Glass if (c == '[') { 1542e192b24SSimon Glass *esc = 2; 1552e192b24SSimon Glass *key = KEY_NONE; 1562e192b24SSimon Glass } else { 1572e192b24SSimon Glass *esc = 0; 1582e192b24SSimon Glass } 1592e192b24SSimon Glass break; 1602e192b24SSimon Glass case 2: 1612e192b24SSimon Glass case 3: 1622e192b24SSimon Glass /* Third char of ANSI (number '1') - optional */ 1632e192b24SSimon Glass if (*esc == 2 && c == '1') { 1642e192b24SSimon Glass *esc = 3; 1652e192b24SSimon Glass *key = KEY_NONE; 1662e192b24SSimon Glass break; 1672e192b24SSimon Glass } 1682e192b24SSimon Glass 1692e192b24SSimon Glass *esc = 0; 1702e192b24SSimon Glass 1712e192b24SSimon Glass /* ANSI 'A' - key up was pressed */ 1722e192b24SSimon Glass if (c == 'A') 1732e192b24SSimon Glass *key = KEY_UP; 1742e192b24SSimon Glass /* ANSI 'B' - key down was pressed */ 1752e192b24SSimon Glass else if (c == 'B') 1762e192b24SSimon Glass *key = KEY_DOWN; 1772e192b24SSimon Glass /* other key was pressed */ 1782e192b24SSimon Glass else 1792e192b24SSimon Glass *key = KEY_NONE; 1802e192b24SSimon Glass 1812e192b24SSimon Glass break; 1822e192b24SSimon Glass } 1832e192b24SSimon Glass 1842e192b24SSimon Glass /* enter key was pressed */ 1852e192b24SSimon Glass if (c == '\r') 1862e192b24SSimon Glass *key = KEY_SELECT; 1872e192b24SSimon Glass } 1882e192b24SSimon Glass 1892e192b24SSimon Glass static char *bootmenu_choice_entry(void *data) 1902e192b24SSimon Glass { 1912e192b24SSimon Glass struct bootmenu_data *menu = data; 1922e192b24SSimon Glass struct bootmenu_entry *iter; 1932e192b24SSimon Glass enum bootmenu_key key = KEY_NONE; 1942e192b24SSimon Glass int esc = 0; 1952e192b24SSimon Glass int i; 1962e192b24SSimon Glass 1972e192b24SSimon Glass while (1) { 1982e192b24SSimon Glass if (menu->delay >= 0) { 1992e192b24SSimon Glass /* Autoboot was not stopped */ 2002e192b24SSimon Glass bootmenu_autoboot_loop(menu, &key, &esc); 2012e192b24SSimon Glass } else { 2022e192b24SSimon Glass /* Some key was pressed, so autoboot was stopped */ 2032e192b24SSimon Glass bootmenu_loop(menu, &key, &esc); 2042e192b24SSimon Glass } 2052e192b24SSimon Glass 2062e192b24SSimon Glass switch (key) { 2072e192b24SSimon Glass case KEY_UP: 2082e192b24SSimon Glass if (menu->active > 0) 2092e192b24SSimon Glass --menu->active; 2102e192b24SSimon Glass /* no menu key selected, regenerate menu */ 2112e192b24SSimon Glass return NULL; 2122e192b24SSimon Glass case KEY_DOWN: 2132e192b24SSimon Glass if (menu->active < menu->count - 1) 2142e192b24SSimon Glass ++menu->active; 2152e192b24SSimon Glass /* no menu key selected, regenerate menu */ 2162e192b24SSimon Glass return NULL; 2172e192b24SSimon Glass case KEY_SELECT: 2182e192b24SSimon Glass iter = menu->first; 2192e192b24SSimon Glass for (i = 0; i < menu->active; ++i) 2202e192b24SSimon Glass iter = iter->next; 2212e192b24SSimon Glass return iter->key; 2222e192b24SSimon Glass default: 2232e192b24SSimon Glass break; 2242e192b24SSimon Glass } 2252e192b24SSimon Glass } 2262e192b24SSimon Glass 2272e192b24SSimon Glass /* never happens */ 2282e192b24SSimon Glass debug("bootmenu: this should not happen"); 2292e192b24SSimon Glass return NULL; 2302e192b24SSimon Glass } 2312e192b24SSimon Glass 2322e192b24SSimon Glass static void bootmenu_destroy(struct bootmenu_data *menu) 2332e192b24SSimon Glass { 2342e192b24SSimon Glass struct bootmenu_entry *iter = menu->first; 2352e192b24SSimon Glass struct bootmenu_entry *next; 2362e192b24SSimon Glass 2372e192b24SSimon Glass while (iter) { 2382e192b24SSimon Glass next = iter->next; 2392e192b24SSimon Glass free(iter->title); 2402e192b24SSimon Glass free(iter->command); 2412e192b24SSimon Glass free(iter); 2422e192b24SSimon Glass iter = next; 2432e192b24SSimon Glass } 2442e192b24SSimon Glass free(menu); 2452e192b24SSimon Glass } 2462e192b24SSimon Glass 2472e192b24SSimon Glass static struct bootmenu_data *bootmenu_create(int delay) 2482e192b24SSimon Glass { 2492e192b24SSimon Glass unsigned short int i = 0; 2502e192b24SSimon Glass const char *option; 2512e192b24SSimon Glass struct bootmenu_data *menu; 2522e192b24SSimon Glass struct bootmenu_entry *iter = NULL; 2532e192b24SSimon Glass 2542e192b24SSimon Glass int len; 2552e192b24SSimon Glass char *sep; 256*f7bb20a5SFrank Wunderlich char *default_str; 2572e192b24SSimon Glass struct bootmenu_entry *entry; 2582e192b24SSimon Glass 2592e192b24SSimon Glass menu = malloc(sizeof(struct bootmenu_data)); 2602e192b24SSimon Glass if (!menu) 2612e192b24SSimon Glass return NULL; 2622e192b24SSimon Glass 2632e192b24SSimon Glass menu->delay = delay; 2642e192b24SSimon Glass menu->active = 0; 2652e192b24SSimon Glass menu->first = NULL; 2662e192b24SSimon Glass 267*f7bb20a5SFrank Wunderlich default_str = env_get("bootmenu_default"); 268*f7bb20a5SFrank Wunderlich if (default_str) 269*f7bb20a5SFrank Wunderlich menu->active = (int)simple_strtol(default_str, NULL, 10); 270*f7bb20a5SFrank Wunderlich 2712e192b24SSimon Glass while ((option = bootmenu_getoption(i))) { 2722e192b24SSimon Glass sep = strchr(option, '='); 2732e192b24SSimon Glass if (!sep) { 2742e192b24SSimon Glass printf("Invalid bootmenu entry: %s\n", option); 2752e192b24SSimon Glass break; 2762e192b24SSimon Glass } 2772e192b24SSimon Glass 2782e192b24SSimon Glass entry = malloc(sizeof(struct bootmenu_entry)); 2792e192b24SSimon Glass if (!entry) 2802e192b24SSimon Glass goto cleanup; 2812e192b24SSimon Glass 2822e192b24SSimon Glass len = sep-option; 2832e192b24SSimon Glass entry->title = malloc(len + 1); 2842e192b24SSimon Glass if (!entry->title) { 2852e192b24SSimon Glass free(entry); 2862e192b24SSimon Glass goto cleanup; 2872e192b24SSimon Glass } 2882e192b24SSimon Glass memcpy(entry->title, option, len); 2892e192b24SSimon Glass entry->title[len] = 0; 2902e192b24SSimon Glass 2912e192b24SSimon Glass len = strlen(sep + 1); 2922e192b24SSimon Glass entry->command = malloc(len + 1); 2932e192b24SSimon Glass if (!entry->command) { 2942e192b24SSimon Glass free(entry->title); 2952e192b24SSimon Glass free(entry); 2962e192b24SSimon Glass goto cleanup; 2972e192b24SSimon Glass } 2982e192b24SSimon Glass memcpy(entry->command, sep + 1, len); 2992e192b24SSimon Glass entry->command[len] = 0; 3002e192b24SSimon Glass 3012e192b24SSimon Glass sprintf(entry->key, "%d", i); 3022e192b24SSimon Glass 3032e192b24SSimon Glass entry->num = i; 3042e192b24SSimon Glass entry->menu = menu; 3052e192b24SSimon Glass entry->next = NULL; 3062e192b24SSimon Glass 3072e192b24SSimon Glass if (!iter) 3082e192b24SSimon Glass menu->first = entry; 3092e192b24SSimon Glass else 3102e192b24SSimon Glass iter->next = entry; 3112e192b24SSimon Glass 3122e192b24SSimon Glass iter = entry; 3132e192b24SSimon Glass ++i; 3142e192b24SSimon Glass 3152e192b24SSimon Glass if (i == MAX_COUNT - 1) 3162e192b24SSimon Glass break; 3172e192b24SSimon Glass } 3182e192b24SSimon Glass 3192e192b24SSimon Glass /* Add U-Boot console entry at the end */ 3202e192b24SSimon Glass if (i <= MAX_COUNT - 1) { 3212e192b24SSimon Glass entry = malloc(sizeof(struct bootmenu_entry)); 3222e192b24SSimon Glass if (!entry) 3232e192b24SSimon Glass goto cleanup; 3242e192b24SSimon Glass 3252e192b24SSimon Glass entry->title = strdup("U-Boot console"); 3262e192b24SSimon Glass if (!entry->title) { 3272e192b24SSimon Glass free(entry); 3282e192b24SSimon Glass goto cleanup; 3292e192b24SSimon Glass } 3302e192b24SSimon Glass 3312e192b24SSimon Glass entry->command = strdup(""); 3322e192b24SSimon Glass if (!entry->command) { 3332e192b24SSimon Glass free(entry->title); 3342e192b24SSimon Glass free(entry); 3352e192b24SSimon Glass goto cleanup; 3362e192b24SSimon Glass } 3372e192b24SSimon Glass 3382e192b24SSimon Glass sprintf(entry->key, "%d", i); 3392e192b24SSimon Glass 3402e192b24SSimon Glass entry->num = i; 3412e192b24SSimon Glass entry->menu = menu; 3422e192b24SSimon Glass entry->next = NULL; 3432e192b24SSimon Glass 3442e192b24SSimon Glass if (!iter) 3452e192b24SSimon Glass menu->first = entry; 3462e192b24SSimon Glass else 3472e192b24SSimon Glass iter->next = entry; 3482e192b24SSimon Glass 3492e192b24SSimon Glass iter = entry; 3502e192b24SSimon Glass ++i; 3512e192b24SSimon Glass } 3522e192b24SSimon Glass 3532e192b24SSimon Glass menu->count = i; 3542e192b24SSimon Glass return menu; 3552e192b24SSimon Glass 3562e192b24SSimon Glass cleanup: 3572e192b24SSimon Glass bootmenu_destroy(menu); 3582e192b24SSimon Glass return NULL; 3592e192b24SSimon Glass } 3602e192b24SSimon Glass 3612e192b24SSimon Glass static void bootmenu_show(int delay) 3622e192b24SSimon Glass { 3632e192b24SSimon Glass int init = 0; 3642e192b24SSimon Glass void *choice = NULL; 3652e192b24SSimon Glass char *title = NULL; 3662e192b24SSimon Glass char *command = NULL; 3672e192b24SSimon Glass struct menu *menu; 3682e192b24SSimon Glass struct bootmenu_data *bootmenu; 3692e192b24SSimon Glass struct bootmenu_entry *iter; 3702e192b24SSimon Glass char *option, *sep; 3712e192b24SSimon Glass 3722e192b24SSimon Glass /* If delay is 0 do not create menu, just run first entry */ 3732e192b24SSimon Glass if (delay == 0) { 3742e192b24SSimon Glass option = bootmenu_getoption(0); 3752e192b24SSimon Glass if (!option) { 3762e192b24SSimon Glass puts("bootmenu option 0 was not found\n"); 3772e192b24SSimon Glass return; 3782e192b24SSimon Glass } 3792e192b24SSimon Glass sep = strchr(option, '='); 3802e192b24SSimon Glass if (!sep) { 3812e192b24SSimon Glass puts("bootmenu option 0 is invalid\n"); 3822e192b24SSimon Glass return; 3832e192b24SSimon Glass } 3842e192b24SSimon Glass run_command(sep+1, 0); 3852e192b24SSimon Glass return; 3862e192b24SSimon Glass } 3872e192b24SSimon Glass 3882e192b24SSimon Glass bootmenu = bootmenu_create(delay); 3892e192b24SSimon Glass if (!bootmenu) 3902e192b24SSimon Glass return; 3912e192b24SSimon Glass 3922e192b24SSimon Glass menu = menu_create(NULL, bootmenu->delay, 1, bootmenu_print_entry, 3932e192b24SSimon Glass bootmenu_choice_entry, bootmenu); 3942e192b24SSimon Glass if (!menu) { 3952e192b24SSimon Glass bootmenu_destroy(bootmenu); 3962e192b24SSimon Glass return; 3972e192b24SSimon Glass } 3982e192b24SSimon Glass 3992e192b24SSimon Glass for (iter = bootmenu->first; iter; iter = iter->next) { 4002e192b24SSimon Glass if (!menu_item_add(menu, iter->key, iter)) 4012e192b24SSimon Glass goto cleanup; 4022e192b24SSimon Glass } 4032e192b24SSimon Glass 4042e192b24SSimon Glass /* Default menu entry is always first */ 4052e192b24SSimon Glass menu_default_set(menu, "0"); 4062e192b24SSimon Glass 4072e192b24SSimon Glass puts(ANSI_CURSOR_HIDE); 4082e192b24SSimon Glass puts(ANSI_CLEAR_CONSOLE); 4092e192b24SSimon Glass printf(ANSI_CURSOR_POSITION, 1, 1); 4102e192b24SSimon Glass 4112e192b24SSimon Glass init = 1; 4122e192b24SSimon Glass 4132e192b24SSimon Glass if (menu_get_choice(menu, &choice)) { 4142e192b24SSimon Glass iter = choice; 4152e192b24SSimon Glass title = strdup(iter->title); 4162e192b24SSimon Glass command = strdup(iter->command); 4172e192b24SSimon Glass } 4182e192b24SSimon Glass 4192e192b24SSimon Glass cleanup: 4202e192b24SSimon Glass menu_destroy(menu); 4212e192b24SSimon Glass bootmenu_destroy(bootmenu); 4222e192b24SSimon Glass 4232e192b24SSimon Glass if (init) { 4242e192b24SSimon Glass puts(ANSI_CURSOR_SHOW); 4252e192b24SSimon Glass puts(ANSI_CLEAR_CONSOLE); 4262e192b24SSimon Glass printf(ANSI_CURSOR_POSITION, 1, 1); 4272e192b24SSimon Glass } 4282e192b24SSimon Glass 4292e192b24SSimon Glass if (title && command) { 4302e192b24SSimon Glass debug("Starting entry '%s'\n", title); 4312e192b24SSimon Glass free(title); 4322e192b24SSimon Glass run_command(command, 0); 4332e192b24SSimon Glass free(command); 4342e192b24SSimon Glass } 4352e192b24SSimon Glass 4362e192b24SSimon Glass #ifdef CONFIG_POSTBOOTMENU 4372e192b24SSimon Glass run_command(CONFIG_POSTBOOTMENU, 0); 4382e192b24SSimon Glass #endif 4392e192b24SSimon Glass } 4402e192b24SSimon Glass 4412e192b24SSimon Glass void menu_display_statusline(struct menu *m) 4422e192b24SSimon Glass { 4432e192b24SSimon Glass struct bootmenu_entry *entry; 4442e192b24SSimon Glass struct bootmenu_data *menu; 4452e192b24SSimon Glass 4462e192b24SSimon Glass if (menu_default_choice(m, (void *)&entry) < 0) 4472e192b24SSimon Glass return; 4482e192b24SSimon Glass 4492e192b24SSimon Glass menu = entry->menu; 4502e192b24SSimon Glass 4512e192b24SSimon Glass printf(ANSI_CURSOR_POSITION, 1, 1); 4522e192b24SSimon Glass puts(ANSI_CLEAR_LINE); 4532e192b24SSimon Glass printf(ANSI_CURSOR_POSITION, 2, 1); 4542e192b24SSimon Glass puts(" *** U-Boot Boot Menu ***"); 4552e192b24SSimon Glass puts(ANSI_CLEAR_LINE_TO_END); 4562e192b24SSimon Glass printf(ANSI_CURSOR_POSITION, 3, 1); 4572e192b24SSimon Glass puts(ANSI_CLEAR_LINE); 4582e192b24SSimon Glass 4592e192b24SSimon Glass /* First 3 lines are bootmenu header + 2 empty lines between entries */ 4602e192b24SSimon Glass printf(ANSI_CURSOR_POSITION, menu->count + 5, 1); 4612e192b24SSimon Glass puts(ANSI_CLEAR_LINE); 4622e192b24SSimon Glass printf(ANSI_CURSOR_POSITION, menu->count + 6, 1); 4632e192b24SSimon Glass puts(" Press UP/DOWN to move, ENTER to select"); 4642e192b24SSimon Glass puts(ANSI_CLEAR_LINE_TO_END); 4652e192b24SSimon Glass printf(ANSI_CURSOR_POSITION, menu->count + 7, 1); 4662e192b24SSimon Glass puts(ANSI_CLEAR_LINE); 4672e192b24SSimon Glass } 4682e192b24SSimon Glass 4692e192b24SSimon Glass #ifdef CONFIG_MENU_SHOW 4702e192b24SSimon Glass int menu_show(int bootdelay) 4712e192b24SSimon Glass { 4722e192b24SSimon Glass bootmenu_show(bootdelay); 4732e192b24SSimon Glass return -1; /* -1 - abort boot and run monitor code */ 4742e192b24SSimon Glass } 4752e192b24SSimon Glass #endif 4762e192b24SSimon Glass 4772e192b24SSimon Glass int do_bootmenu(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 4782e192b24SSimon Glass { 4792e192b24SSimon Glass char *delay_str = NULL; 4802e192b24SSimon Glass int delay = 10; 4812e192b24SSimon Glass 4822e192b24SSimon Glass #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) 4832e192b24SSimon Glass delay = CONFIG_BOOTDELAY; 4842e192b24SSimon Glass #endif 4852e192b24SSimon Glass 4862e192b24SSimon Glass if (argc >= 2) 4872e192b24SSimon Glass delay_str = argv[1]; 4882e192b24SSimon Glass 4892e192b24SSimon Glass if (!delay_str) 49000caae6dSSimon Glass delay_str = env_get("bootmenu_delay"); 4912e192b24SSimon Glass 4922e192b24SSimon Glass if (delay_str) 4932e192b24SSimon Glass delay = (int)simple_strtol(delay_str, NULL, 10); 4942e192b24SSimon Glass 4952e192b24SSimon Glass bootmenu_show(delay); 4962e192b24SSimon Glass return 0; 4972e192b24SSimon Glass } 4982e192b24SSimon Glass 4992e192b24SSimon Glass U_BOOT_CMD( 5002e192b24SSimon Glass bootmenu, 2, 1, do_bootmenu, 5012e192b24SSimon Glass "ANSI terminal bootmenu", 5022e192b24SSimon Glass "[delay]\n" 5032e192b24SSimon Glass " - show ANSI terminal bootmenu with autoboot delay" 5042e192b24SSimon Glass ); 505