From 5a15437610e8e8c68dc347845a83d0cbad80ca08 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Tue, 19 Jan 2021 10:58:48 +0800 Subject: [PATCH 51/71] cmd: bootmenu: add ability to select item by shortkey Add ability to use shortkey to select item for bootmenu command Signed-off-by: Weijie Gao --- cmd/bootmenu.c | 28 +++++++++++++++++++++++--- common/menu.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/cli.h | 2 ++ include/menu.h | 3 +++ 4 files changed, 84 insertions(+), 3 deletions(-) --- a/cmd/bootmenu.c +++ b/cmd/bootmenu.c @@ -114,6 +114,8 @@ static char *bootmenu_choice_entry(void ++menu->active; /* no menu key selected, regenerate menu */ return NULL; + case BKEY_CHOICE: + menu->active = cch->choice; case BKEY_SELECT: iter = menu->first; for (i = 0; i < menu->active; ++i) @@ -182,6 +184,9 @@ static int prepare_bootmenu_entry(struct unsigned short int i = *index; struct bootmenu_entry *entry = NULL; struct bootmenu_entry *iter = *current; + char *choice_option; + char choice_char; + int len; while ((option = bootmenu_getoption(i))) { @@ -196,11 +201,28 @@ static int prepare_bootmenu_entry(struct if (!entry) return -ENOMEM; - entry->title = strndup(option, sep - option); + /* Add BKEY_CHOICE support: '%c. %s\0' : len --> len + 4 */ + len = sep - option + 4; + + choice_option = malloc(len); + if (!choice_option) { + free(entry->title); + free(entry); + return -ENOMEM; + } + + if (!get_choice_char(i, &choice_char)) + len = snprintf(choice_option, len, "%c. %s", choice_char, option); + else + len = snprintf(choice_option, len, " %s", option); + + entry->title = strndup(choice_option, len); + if (!entry->title) { free(entry); return -ENOMEM; } + free(choice_option); entry->command = strdup(sep + 1); if (!entry->command) { @@ -382,9 +404,9 @@ static struct bootmenu_data *bootmenu_cr /* Add Quit entry if exiting bootmenu is disabled */ if (!IS_ENABLED(CONFIG_BOOTMENU_DISABLE_UBOOT_CONSOLE)) - entry->title = strdup("Exit"); + entry->title = strdup("0. Exit"); else - entry->title = strdup("Quit"); + entry->title = strdup("0. Quit"); if (!entry->title) { free(entry); --- a/common/menu.c +++ b/common/menu.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -49,6 +50,33 @@ struct menu { int item_cnt; }; +const char choice_chars[] = { + '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', + 'u', 'v', 'w', 'x', 'y', 'z' +}; + +static int find_choice(char choice) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(choice_chars); i++) + if (tolower(choice) == choice_chars[i]) + return i; + + return -1; +} + +int get_choice_char(int index, char *result) +{ + if (index < ARRAY_SIZE(choice_chars)) + *result = choice_chars[index]; + else + return -1; + return 0; +} + /* * An iterator function for menu items. callback will be called for each item * in m, with m, a pointer to the item, and extra being passed to callback. If @@ -441,6 +469,7 @@ enum bootmenu_key bootmenu_autoboot_loop { enum bootmenu_key key = BKEY_NONE; int i, c; + int choice; while (menu->delay > 0) { if (ansi) @@ -458,6 +487,18 @@ enum bootmenu_key bootmenu_autoboot_loop menu->delay = -1; c = getchar(); + choice = find_choice(c); + if ((choice >= 0 && + choice < menu->count - 1)) { + cch->choice = choice; + key = BKEY_CHOICE; + break; + } else if (c == '0') { + cch->choice = menu->count - 1; + key = BKEY_CHOICE; + break; + } + ichar = cli_ch_process(cch, c); switch (ichar) { @@ -537,6 +578,7 @@ enum bootmenu_key bootmenu_loop(struct b { enum bootmenu_key key; int c, errchar = 0; + int choice; c = cli_ch_process(cch, 0); if (!c) { @@ -548,6 +590,18 @@ enum bootmenu_key bootmenu_loop(struct b } if (!c) { c = getchar(); + + choice = find_choice(c); + if ((choice >= 0 && + choice < menu->count - 1)) { + cch->choice = choice; + return BKEY_CHOICE; + + } else if (c == '0') { + cch->choice = menu->count - 1; + return BKEY_CHOICE; + } + c = cli_ch_process(cch, c); } } --- a/include/cli.h +++ b/include/cli.h @@ -23,6 +23,8 @@ struct cli_ch_state { char esc_save[8]; int emit_upto; bool emitting; + /* mediatek bootmenu choice feature */ + char choice; }; /** --- a/include/menu.h +++ b/include/menu.h @@ -37,6 +37,8 @@ int menu_default_choice(struct menu *m, */ int menu_show(int bootdelay); +int get_choice_char(int index, char *result); + struct bootmenu_data { int delay; /* delay for autoboot */ int active; /* active menu entry */ @@ -51,6 +53,7 @@ enum bootmenu_key { BKEY_UP, BKEY_DOWN, BKEY_SELECT, + BKEY_CHOICE, BKEY_QUIT, BKEY_SAVE,