From a06004f4c668abd7c760a2818d0a8205da7568e7 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 26 Apr 2016 15:29:25 +0200 Subject: [PATCH v3] Add hidden menu entries The menu infrastructure is quite powerful. It allows you to define menu entries that can contain arbitrary grub commands that can do a lot more than just boot kernel entries. For some of these it makes sense to hide them inside the normal menu though and instead have them available through hotkeys that get advertised differently. My main use case is to switch to the serial console when gfxterm is loaded. So this patch adds support for hidden menu entries that are accessible using hotkeys, but are not accessible in the grub menu. Signed-off-by: Alexander Graf --- v1 -> v2: - fix default entry selection v2 -> v3: - replace "--hidden" parameter with new command "hiddenentry" diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c index dd9d9f1..b282c4f 100644 --- a/grub-core/commands/legacycfg.c +++ b/grub-core/commands/legacycfg.c @@ -133,7 +133,7 @@ legacy_file (const char *filename) args[0] = oldname; grub_normal_add_menu_entry (1, args, NULL, NULL, "legacy", NULL, NULL, - entrysrc, 0); + entrysrc, 0, 0); grub_free (args); entrysrc[0] = 0; grub_free (oldname); @@ -186,7 +186,7 @@ legacy_file (const char *filename) } args[0] = entryname; grub_normal_add_menu_entry (1, args, NULL, NULL, NULL, - NULL, NULL, entrysrc, 0); + NULL, NULL, entrysrc, 0, 0); grub_free (args); } diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c index 58d4dad..b4d6c31 100644 --- a/grub-core/commands/menuentry.c +++ b/grub-core/commands/menuentry.c @@ -78,7 +78,7 @@ grub_normal_add_menu_entry (int argc, const char **args, char **classes, const char *id, const char *users, const char *hotkey, const char *prefix, const char *sourcecode, - int submenu) + int submenu, int hidden) { int menu_hotkey = 0; char **menu_args = NULL; @@ -188,8 +188,11 @@ grub_normal_add_menu_entry (int argc, const char **args, (*last)->args = menu_args; (*last)->sourcecode = menu_sourcecode; (*last)->submenu = submenu; + (*last)->hidden = hidden; + + if (!hidden) + menu->size++; - menu->size++; return GRUB_ERR_NONE; fail: @@ -286,7 +289,8 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args) users, ctxt->state[2].arg, 0, ctxt->state[3].arg, - ctxt->extcmd->cmd->name[0] == 's'); + ctxt->extcmd->cmd->name[0] == 's', + ctxt->extcmd->cmd->name[0] == 'h'); src = args[argc - 1]; args[argc - 1] = NULL; @@ -303,7 +307,8 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args) ctxt->state[0].args, ctxt->state[4].arg, users, ctxt->state[2].arg, prefix, src + 1, - ctxt->extcmd->cmd->name[0] == 's'); + ctxt->extcmd->cmd->name[0] == 's', + ctxt->extcmd->cmd->name[0] == 'h'); src[len - 1] = ch; args[argc - 1] = src; @@ -311,7 +316,7 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args) return r; } -static grub_extcmd_t cmd, cmd_sub; +static grub_extcmd_t cmd, cmd_sub, cmd_hidden; void grub_menu_init (void) @@ -327,6 +332,13 @@ grub_menu_init (void) | GRUB_COMMAND_FLAG_EXTRACTOR, N_("BLOCK"), N_("Define a submenu."), options); + cmd_hidden = grub_register_extcmd ("hiddenentry", grub_cmd_menuentry, + GRUB_COMMAND_FLAG_BLOCKS + | GRUB_COMMAND_ACCEPT_DASH + | GRUB_COMMAND_FLAG_EXTRACTOR, + N_("BLOCK"), + N_("Define a hidden menu entry."), + options); } void diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c index 719e2fb..2a151fe 100644 --- a/grub-core/normal/menu.c +++ b/grub-core/normal/menu.c @@ -40,6 +40,8 @@ grub_err_t (*grub_gfxmenu_try_hook) (int entry, grub_menu_t menu, int nested) = NULL; +#define MENU_INCLUDE_HIDDEN 0x10000 + enum timeout_style { TIMEOUT_STYLE_MENU, TIMEOUT_STYLE_COUNTDOWN, @@ -80,8 +82,20 @@ grub_menu_get_entry (grub_menu_t menu, int no) { grub_menu_entry_t e; - for (e = menu->entry_list; e && no > 0; e = e->next, no--) - ; + if (no & MENU_INCLUDE_HIDDEN) { + no &= ~MENU_INCLUDE_HIDDEN; + + for (e = menu->entry_list; e && no > 0; e = e->next, no--) + ; + } else { + for (e = menu->entry_list; e && no > 0; e = e->next, no--) { + /* Skip hidden entries */ + while (e && e->hidden) + e = e->next; + } + while (e && e->hidden) + e = e->next; + } return e; } @@ -93,10 +107,10 @@ get_entry_index_by_hotkey (grub_menu_t menu, int hotkey) grub_menu_entry_t entry; int i; - for (i = 0, entry = menu->entry_list; i < menu->size; + for (i = 0, entry = menu->entry_list; entry; i++, entry = entry->next) if (entry->hotkey == hotkey) - return i; + return i | MENU_INCLUDE_HIDDEN; return -1; } @@ -510,6 +524,10 @@ get_entry_number (grub_menu_t menu, const char *name) grub_menu_entry_t e = menu->entry_list; int i; + /* Skip hidden entries */ + while (e && e->hidden) + e = e->next; + grub_errno = GRUB_ERR_NONE; for (i = 0; e; i++) @@ -521,6 +539,10 @@ get_entry_number (grub_menu_t menu, const char *name) break; } e = e->next; + + /* Skip hidden entries */ + while (e && e->hidden) + e = e->next; } if (! e) diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c index e22bb91..4ac2d6b 100644 --- a/grub-core/normal/menu_text.c +++ b/grub-core/normal/menu_text.c @@ -290,6 +290,10 @@ print_entries (grub_menu_t menu, const struct menu_viewer_data *data) e, data); if (e) e = e->next; + + /* Skip hidden entries */ + while (e && e->hidden) + e = e->next; } grub_term_gotoxy (data->term, diff --git a/include/grub/menu.h b/include/grub/menu.h index ee2b5e9..eb8a86b 100644 --- a/include/grub/menu.h +++ b/include/grub/menu.h @@ -58,6 +58,8 @@ struct grub_menu_entry int submenu; + int hidden; + /* The next element. */ struct grub_menu_entry *next; }; diff --git a/include/grub/normal.h b/include/grub/normal.h index 218cbab..bcb4124 100644 --- a/include/grub/normal.h +++ b/include/grub/normal.h @@ -145,7 +145,7 @@ grub_normal_add_menu_entry (int argc, const char **args, char **classes, const char *id, const char *users, const char *hotkey, const char *prefix, const char *sourcecode, - int submenu); + int submenu, int hidden); grub_err_t grub_normal_set_password (const char *user, const char *password);