1diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c
2index e9e9d94ef..54e08a1b4 100644
3--- a/grub-core/commands/legacycfg.c
4+++ b/grub-core/commands/legacycfg.c
5@@ -143,7 +143,7 @@ legacy_file (const char *filename)
6 args[0] = oldname;
7 grub_normal_add_menu_entry (1, args, NULL, NULL, "legacy",
8 NULL, NULL,
9- entrysrc, 0);
10+ entrysrc, 0, 0);
11 grub_free (args);
12 entrysrc[0] = 0;
13 grub_free (oldname);
14@@ -205,7 +205,7 @@ legacy_file (const char *filename)
15 }
16 args[0] = entryname;
17 grub_normal_add_menu_entry (1, args, NULL, NULL, NULL,
18- NULL, NULL, entrysrc, 0);
19+ NULL, NULL, entrysrc, 0, 0);
20 grub_free (args);
21 }
22
23diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c
24index 720e6d8ea..50632ccce 100644
25--- a/grub-core/commands/menuentry.c
26+++ b/grub-core/commands/menuentry.c
27@@ -78,7 +78,7 @@ grub_normal_add_menu_entry (int argc, const char **args,
28 char **classes, const char *id,
29 const char *users, const char *hotkey,
30 const char *prefix, const char *sourcecode,
31- int submenu)
32+ int submenu, int hidden)
33 {
34 int menu_hotkey = 0;
35 char **menu_args = NULL;
36@@ -188,8 +188,11 @@ grub_normal_add_menu_entry (int argc, const char **args,
37 (*last)->args = menu_args;
38 (*last)->sourcecode = menu_sourcecode;
39 (*last)->submenu = submenu;
40+ (*last)->hidden = hidden;
41+
42+ if (!hidden)
43+ menu->size++;
44
45- menu->size++;
46 return GRUB_ERR_NONE;
47
48 fail:
49@@ -286,7 +289,8 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args)
50 users,
51 ctxt->state[2].arg, 0,
52 ctxt->state[3].arg,
53- ctxt->extcmd->cmd->name[0] == 's');
54+ ctxt->extcmd->cmd->name[0] == 's',
55+ ctxt->extcmd->cmd->name[0] == 'h');
56
57 src = args[argc - 1];
58 args[argc - 1] = NULL;
59@@ -303,7 +307,8 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args)
60 ctxt->state[0].args, ctxt->state[4].arg,
61 users,
62 ctxt->state[2].arg, prefix, src + 1,
63- ctxt->extcmd->cmd->name[0] == 's');
64+ ctxt->extcmd->cmd->name[0] == 's',
65+ ctxt->extcmd->cmd->name[0] == 'h');
66
67 src[len - 1] = ch;
68 args[argc - 1] = src;
69@@ -311,7 +316,7 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args)
70 return r;
71 }
72
73-static grub_extcmd_t cmd, cmd_sub;
74+static grub_extcmd_t cmd, cmd_sub, cmd_hidden;
75
76 void
77 grub_menu_init (void)
78@@ -327,6 +332,12 @@ grub_menu_init (void)
79 | GRUB_COMMAND_FLAG_EXTRACTOR,
80 N_("BLOCK"), N_("Define a submenu."),
81 options);
82+ cmd_hidden = grub_register_extcmd ("hiddenentry", grub_cmd_menuentry,
83+ GRUB_COMMAND_FLAG_BLOCKS
84+ | GRUB_COMMAND_ACCEPT_DASH
85+ | GRUB_COMMAND_FLAG_EXTRACTOR,
86+ N_("BLOCK"), N_("Define a hidden menu entry."),
87+ options);
88 }
89
90 void
91diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c
92index 6a90e091f..4236f55bc 100644
93--- a/grub-core/normal/menu.c
94+++ b/grub-core/normal/menu.c
95@@ -37,6 +37,8 @@
96 entry failing to boot. */
97 #define DEFAULT_ENTRY_ERROR_DELAY_MS 2500
98
99+#define MENU_INCLUDE_HIDDEN 0x10000
100+
101 grub_err_t (*grub_gfxmenu_try_hook) (int entry, grub_menu_t menu,
102 int nested) = NULL;
103
104@@ -80,8 +82,20 @@ grub_menu_get_entry (grub_menu_t menu, int no)
105 {
106 grub_menu_entry_t e;
107
108- for (e = menu->entry_list; e && no > 0; e = e->next, no--)
109- ;
110+ if (no & MENU_INCLUDE_HIDDEN) {
111+ no &= ~MENU_INCLUDE_HIDDEN;
112+
113+ for (e = menu->entry_list; e && no > 0; e = e->next, no--)
114+ ;
115+ } else {
116+ for (e = menu->entry_list; e && no > 0; e = e->next, no--) {
117+ /* Skip hidden entries */
118+ while (e && e->hidden)
119+ e = e->next;
120+ }
121+ while (e && e->hidden)
122+ e = e->next;
123+ }
124
125 return e;
126 }
127@@ -93,10 +107,10 @@ get_entry_index_by_hotkey (grub_menu_t menu, int hotkey)
128 grub_menu_entry_t entry;
129 int i;
130
131- for (i = 0, entry = menu->entry_list; i < menu->size;
132+ for (i = 0, entry = menu->entry_list; entry;
133 i++, entry = entry->next)
134 if (entry->hotkey == hotkey)
135- return i;
136+ return i | MENU_INCLUDE_HIDDEN;
137
138 return -1;
139 }
140@@ -509,6 +523,10 @@ get_entry_number (grub_menu_t menu, const char *name)
141 grub_menu_entry_t e = menu->entry_list;
142 int i;
143
144+ /* Skip hidden entries */
145+ while (e && e->hidden)
146+ e = e->next;
147+
148 grub_errno = GRUB_ERR_NONE;
149
150 for (i = 0; e; i++)
151@@ -520,6 +538,10 @@ get_entry_number (grub_menu_t menu, const char *name)
152 break;
153 }
154 e = e->next;
155+
156+ /* Skip hidden entries */
157+ while (e && e->hidden)
158+ e = e->next;
159 }
160
161 if (! e)
162diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c
163index b1321eb26..d2e46cac8 100644
164--- a/grub-core/normal/menu_text.c
165+++ b/grub-core/normal/menu_text.c
166@@ -289,7 +289,11 @@ print_entries (grub_menu_t menu, const struct menu_viewer_data *data)
167 print_entry (data->geo.first_entry_y + i, data->offset == i,
168 e, data);
169 if (e)
170- e = e->next;
171+ e = e->next;
172+
173+ /* Skip hidden entries */
174+ while (e && e->hidden)
175+ e = e->next;
176 }
177
178 grub_term_gotoxy (data->term,
179diff --git a/include/grub/menu.h b/include/grub/menu.h
180index ee2b5e910..eb8a86ba9 100644
181--- a/include/grub/menu.h
182+++ b/include/grub/menu.h
183@@ -58,6 +58,8 @@ struct grub_menu_entry
184
185 int submenu;
186
187+ int hidden;
188+
189 /* The next element. */
190 struct grub_menu_entry *next;
191 };
192diff --git a/include/grub/normal.h b/include/grub/normal.h
193index 218cbabcc..bcb412466 100644
194--- a/include/grub/normal.h
195+++ b/include/grub/normal.h
196@@ -145,7 +145,7 @@ grub_normal_add_menu_entry (int argc, const char **args, char **classes,
197 const char *id,
198 const char *users, const char *hotkey,
199 const char *prefix, const char *sourcecode,
200- int submenu);
201+ int submenu, int hidden);
202
203 grub_err_t
204 grub_normal_set_password (const char *user, const char *password);