~hamo/ubuntu/precise/grub2/grub2.hi_res

« back to all changes in this revision

Viewing changes to normal/menu.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Evan Broder, Mario Limonciello
  • Date: 2010-11-24 13:59:55 UTC
  • mfrom: (1.17.6 upstream) (17.6.15 experimental)
  • Revision ID: james.westby@ubuntu.com-20101124135955-r6ii5sepayr7jt53
Tags: 1.99~20101124-1ubuntu1
[ Colin Watson ]
* Resynchronise with Debian experimental.  Remaining changes:
  - Adjust for default Ubuntu boot options ("quiet splash").
  - Default to hiding the menu; holding down Shift at boot will show it.
  - Set a monochromatic theme for Ubuntu.
  - Apply Ubuntu GRUB Legacy changes to legacy update-grub script: title,
    recovery mode, quiet option, tweak how memtest86+ is displayed, and
    use UUIDs where appropriate.
  - Fix backslash-escaping in merge_debconf_into_conf.
  - Remove "GNU/Linux" from default distributor string.
  - Add crashkernel= options if kdump and makedumpfile are available.
  - If other operating systems are installed, then automatically unhide
    the menu.  Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus
    if available to check whether Shift is pressed.  If it is, show the
    menu, otherwise boot immediately.  If keystatus is not available, then
    fall back to a short delay interruptible with Escape.
  - Allow Shift to interrupt 'sleep --interruptible'.
  - Don't display introductory message about line editing unless we're
    actually offering a shell prompt.  Don't clear the screen just before
    booting if we never drew the menu in the first place.
  - Remove some verbose messages printed before reading the configuration
    file.
  - Suppress progress messages as the kernel and initrd load for
    non-recovery kernel menu entries.
  - Change prepare_grub_to_access_device to handle filesystems
    loop-mounted on file images.
  - Ignore devices loop-mounted from files in 10_linux.
  - Show the boot menu if the previous boot failed, that is if it failed
    to get to the end of one of the normal runlevels.
  - Don't generate /boot/grub/device.map during grub-install or
    grub-mkconfig by default.
  - Adjust upgrade version checks for Ubuntu.
  - Don't display "GRUB loading" unless Shift is held down.
  - Adjust versions of grub-doc and grub-legacy-doc conflicts to tolerate
    our backport of the grub-doc split.
  - Fix LVM/RAID probing in the absence of /boot/grub/device.map.
  - Look for .mo files in /usr/share/locale-langpack as well, in
    preference.
  - Make sure GRUB_TIMEOUT isn't quoted unnecessarily.
  - Probe all devices in 'grub-probe --target=drive' if
    /boot/grub/device.map is missing.
  - Build-depend on qemu-kvm rather than qemu-system for grub-pc tests.
  - Use qemu rather than qemu-system-i386.
  - Program vesafb on BIOS systems rather than efifb.
  - Add a grub-rescue-efi-amd64 package containing a rescue CD-ROM image
    for EFI-AMD64.
  - On Wubi, don't ask for an install device, but just update wubildr
    using the diverted grub-install.
  - When embedding the core image in a post-MBR gap, check for and avoid
    sectors matching any of a list of known signatures.
  - Disable video_bochs and video_cirrus on PC BIOS systems, as probing
    PCI space seems to break on some systems.
* Downgrade "ACPI shutdown failed" error to a debug message, since it can
  cause spurious test failures.

[ Evan Broder ]
* Enable lua from grub-extras.
* Incorporate the bitop library into lua.
* Add enum_pci function to grub module in lua.
* Switch back to gfxpayload=keep by default, unless the video hardware
  is known to not support it.

[ Mario Limonciello ]
* Built part_msdos and vfat into bootx64.efi (LP: #677758)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* menu.c - General supporting functionality for menus.  */
2
 
/*
3
 
 *  GRUB  --  GRand Unified Bootloader
4
 
 *  Copyright (C) 2003,2004,2005,2006,2007,2008,2009,2010  Free Software Foundation, Inc.
5
 
 *
6
 
 *  GRUB is free software: you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation, either version 3 of the License, or
9
 
 *  (at your option) any later version.
10
 
 *
11
 
 *  GRUB is distributed in the hope that it will be useful,
12
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 *  GNU General Public License for more details.
15
 
 *
16
 
 *  You should have received a copy of the GNU General Public License
17
 
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
18
 
 */
19
 
 
20
 
#include <grub/normal.h>
21
 
#include <grub/misc.h>
22
 
#include <grub/loader.h>
23
 
#include <grub/mm.h>
24
 
#include <grub/time.h>
25
 
#include <grub/env.h>
26
 
#include <grub/menu_viewer.h>
27
 
#include <grub/command.h>
28
 
#include <grub/parser.h>
29
 
#include <grub/auth.h>
30
 
#include <grub/i18n.h>
31
 
#include <grub/term.h>
32
 
#include <grub/script_sh.h>
33
 
 
34
 
/* Time to delay after displaying an error message about a default/fallback
35
 
   entry failing to boot.  */
36
 
#define DEFAULT_ENTRY_ERROR_DELAY_MS  2500
37
 
 
38
 
grub_err_t (*grub_gfxmenu_try_hook) (int entry, grub_menu_t menu,
39
 
                                     int nested) = NULL;
40
 
 
41
 
/* Wait until the user pushes any key so that the user
42
 
   can see what happened.  */
43
 
void
44
 
grub_wait_after_message (void)
45
 
{
46
 
  grub_xputs ("\n");
47
 
  grub_printf_ (N_("Press any key to continue..."));
48
 
  (void) grub_getkey ();
49
 
  grub_xputs ("\n");
50
 
}
51
 
 
52
 
/* Get a menu entry by its index in the entry list.  */
53
 
grub_menu_entry_t
54
 
grub_menu_get_entry (grub_menu_t menu, int no)
55
 
{
56
 
  grub_menu_entry_t e;
57
 
 
58
 
  for (e = menu->entry_list; e && no > 0; e = e->next, no--)
59
 
    ;
60
 
 
61
 
  return e;
62
 
}
63
 
 
64
 
/* Return the current timeout. If the variable "timeout" is not set or
65
 
   invalid, return -1.  */
66
 
int
67
 
grub_menu_get_timeout (void)
68
 
{
69
 
  char *val;
70
 
  int timeout;
71
 
 
72
 
  val = grub_env_get ("timeout");
73
 
  if (! val)
74
 
    return -1;
75
 
 
76
 
  grub_error_push ();
77
 
 
78
 
  timeout = (int) grub_strtoul (val, 0, 0);
79
 
 
80
 
  /* If the value is invalid, unset the variable.  */
81
 
  if (grub_errno != GRUB_ERR_NONE)
82
 
    {
83
 
      grub_env_unset ("timeout");
84
 
      grub_errno = GRUB_ERR_NONE;
85
 
      timeout = -1;
86
 
    }
87
 
 
88
 
  grub_error_pop ();
89
 
 
90
 
  return timeout;
91
 
}
92
 
 
93
 
/* Set current timeout in the variable "timeout".  */
94
 
void
95
 
grub_menu_set_timeout (int timeout)
96
 
{
97
 
  /* Ignore TIMEOUT if it is zero, because it will be unset really soon.  */
98
 
  if (timeout > 0)
99
 
    {
100
 
      char buf[16];
101
 
 
102
 
      grub_snprintf (buf, sizeof (buf), "%d", timeout);
103
 
      grub_env_set ("timeout", buf);
104
 
    }
105
 
}
106
 
 
107
 
/* Get the first entry number from the value of the environment variable NAME,
108
 
   which is a space-separated list of non-negative integers.  The entry number
109
 
   which is returned is stripped from the value of NAME.  If no entry number
110
 
   can be found, -1 is returned.  */
111
 
static int
112
 
get_and_remove_first_entry_number (const char *name)
113
 
{
114
 
  char *val;
115
 
  char *tail;
116
 
  int entry;
117
 
 
118
 
  val = grub_env_get (name);
119
 
  if (! val)
120
 
    return -1;
121
 
 
122
 
  grub_error_push ();
123
 
 
124
 
  entry = (int) grub_strtoul (val, &tail, 0);
125
 
 
126
 
  if (grub_errno == GRUB_ERR_NONE)
127
 
    {
128
 
      /* Skip whitespace to find the next digit.  */
129
 
      while (*tail && grub_isspace (*tail))
130
 
        tail++;
131
 
      grub_env_set (name, tail);
132
 
    }
133
 
  else
134
 
    {
135
 
      grub_env_unset (name);
136
 
      grub_errno = GRUB_ERR_NONE;
137
 
      entry = -1;
138
 
    }
139
 
 
140
 
  grub_error_pop ();
141
 
 
142
 
  return entry;
143
 
}
144
 
 
145
 
static void
146
 
grub_menu_execute_entry_real (grub_menu_entry_t entry)
147
 
{
148
 
  const char *source;
149
 
 
150
 
  auto grub_err_t getline (char **line, int cont);
151
 
  grub_err_t getline (char **line, int cont __attribute__ ((unused)))
152
 
  {
153
 
    const char *p;
154
 
 
155
 
    if (!source)
156
 
      {
157
 
        *line = 0;
158
 
        return 0;
159
 
      }
160
 
 
161
 
    p = grub_strchr (source, '\n');
162
 
 
163
 
    if (p)
164
 
      *line = grub_strndup (source, p - source);
165
 
    else
166
 
      *line = grub_strdup (source);
167
 
    source = p ? p + 1 : 0;
168
 
    return 0;
169
 
  }
170
 
 
171
 
  source = entry->sourcecode;
172
 
 
173
 
  while (source)
174
 
    {
175
 
      char *line;
176
 
 
177
 
      getline (&line, 0);
178
 
      grub_normal_parse_line (line, getline);
179
 
      grub_free (line);
180
 
    }
181
 
}
182
 
 
183
 
/* Run a menu entry.  */
184
 
void
185
 
grub_menu_execute_entry(grub_menu_entry_t entry)
186
 
{
187
 
  grub_err_t err = GRUB_ERR_NONE;
188
 
 
189
 
  if (entry->restricted)
190
 
    err = grub_auth_check_authentication (entry->users);
191
 
 
192
 
  if (err)
193
 
    {
194
 
      grub_print_error ();
195
 
      grub_errno = GRUB_ERR_NONE;
196
 
      return;
197
 
    }
198
 
 
199
 
  grub_env_set ("chosen", entry->title);
200
 
 
201
 
  grub_menu_execute_entry_real (entry);
202
 
 
203
 
  if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
204
 
    /* Implicit execution of boot, only if something is loaded.  */
205
 
    grub_command_execute ("boot", 0, 0);
206
 
}
207
 
 
208
 
/* Execute ENTRY from the menu MENU, falling back to entries specified
209
 
   in the environment variable "fallback" if it fails.  CALLBACK is a
210
 
   pointer to a struct of function pointers which are used to allow the
211
 
   caller provide feedback to the user.  */
212
 
void
213
 
grub_menu_execute_with_fallback (grub_menu_t menu,
214
 
                                 grub_menu_entry_t entry,
215
 
                                 grub_menu_execute_callback_t callback,
216
 
                                 void *callback_data)
217
 
{
218
 
  int fallback_entry;
219
 
 
220
 
  callback->notify_booting (entry, callback_data);
221
 
 
222
 
  grub_menu_execute_entry (entry);
223
 
 
224
 
  /* Deal with fallback entries.  */
225
 
  while ((fallback_entry = get_and_remove_first_entry_number ("fallback"))
226
 
         >= 0)
227
 
    {
228
 
      grub_print_error ();
229
 
      grub_errno = GRUB_ERR_NONE;
230
 
 
231
 
      entry = grub_menu_get_entry (menu, fallback_entry);
232
 
      callback->notify_fallback (entry, callback_data);
233
 
      grub_menu_execute_entry (entry);
234
 
      /* If the function call to execute the entry returns at all, then this is
235
 
         taken to indicate a boot failure.  For menu entries that do something
236
 
         other than actually boot an operating system, this could assume
237
 
         incorrectly that something failed.  */
238
 
    }
239
 
 
240
 
  callback->notify_failure (callback_data);
241
 
}
242
 
 
243
 
static struct grub_menu_viewer *viewers;
244
 
 
245
 
static void
246
 
menu_set_chosen_entry (int entry)
247
 
{
248
 
  struct grub_menu_viewer *cur;
249
 
  for (cur = viewers; cur; cur = cur->next)
250
 
    cur->set_chosen_entry (entry, cur->data);
251
 
}
252
 
 
253
 
static void
254
 
menu_print_timeout (int timeout)
255
 
{
256
 
  struct grub_menu_viewer *cur;
257
 
  for (cur = viewers; cur; cur = cur->next)
258
 
    cur->print_timeout (timeout, cur->data);
259
 
}
260
 
 
261
 
static void
262
 
menu_fini (void)
263
 
{
264
 
  struct grub_menu_viewer *cur, *next;
265
 
  for (cur = viewers; cur; cur = next)
266
 
    {
267
 
      next = cur->next;
268
 
      cur->fini (cur->data);
269
 
      grub_free (cur);
270
 
    }
271
 
  viewers = NULL;
272
 
}
273
 
 
274
 
static void
275
 
menu_init (int entry, grub_menu_t menu, int nested)
276
 
{
277
 
  struct grub_term_output *term;
278
 
 
279
 
  FOR_ACTIVE_TERM_OUTPUTS(term)
280
 
  {
281
 
    grub_err_t err;
282
 
 
283
 
    if (grub_gfxmenu_try_hook && grub_strcmp (term->name, "gfxterm") == 0)
284
 
      {
285
 
        err = grub_gfxmenu_try_hook (entry, menu, nested);
286
 
        if(!err)
287
 
          continue;
288
 
        grub_errno = GRUB_ERR_NONE;
289
 
      }
290
 
 
291
 
    err = grub_menu_try_text (term, entry, menu, nested);
292
 
    if(!err)
293
 
      continue;
294
 
    grub_print_error ();
295
 
    grub_errno = GRUB_ERR_NONE;
296
 
  }
297
 
}
298
 
 
299
 
static void
300
 
clear_timeout (void)
301
 
{
302
 
  struct grub_menu_viewer *cur;
303
 
  for (cur = viewers; cur; cur = cur->next)
304
 
    cur->clear_timeout (cur->data);
305
 
}
306
 
 
307
 
void
308
 
grub_menu_register_viewer (struct grub_menu_viewer *viewer)
309
 
{
310
 
  viewer->next = viewers;
311
 
  viewers = viewer;
312
 
}
313
 
 
314
 
/* Get the entry number from the variable NAME.  */
315
 
static int
316
 
get_entry_number (grub_menu_t menu, const char *name)
317
 
{
318
 
  char *val;
319
 
  int entry;
320
 
 
321
 
  val = grub_env_get (name);
322
 
  if (! val)
323
 
    return -1;
324
 
 
325
 
  grub_error_push ();
326
 
 
327
 
  entry = (int) grub_strtoul (val, 0, 0);
328
 
 
329
 
  if (grub_errno == GRUB_ERR_BAD_NUMBER)
330
 
    {
331
 
      /* See if the variable matches the title of a menu entry.  */
332
 
      grub_menu_entry_t e = menu->entry_list;
333
 
      int i;
334
 
 
335
 
      grub_errno = GRUB_ERR_NONE;
336
 
 
337
 
      for (i = 0; e; i++)
338
 
        {
339
 
          if (grub_strcmp (e->title, val) == 0)
340
 
            {
341
 
              entry = i;
342
 
              break;
343
 
            }
344
 
          e = e->next;
345
 
        }
346
 
 
347
 
      if (! e)
348
 
        entry = -1;
349
 
    }
350
 
 
351
 
  if (grub_errno != GRUB_ERR_NONE)
352
 
    {
353
 
      grub_errno = GRUB_ERR_NONE;
354
 
      entry = -1;
355
 
    }
356
 
 
357
 
  grub_error_pop ();
358
 
 
359
 
  return entry;
360
 
}
361
 
 
362
 
#define GRUB_MENU_PAGE_SIZE 10
363
 
 
364
 
/* Show the menu and handle menu entry selection.  Returns the menu entry
365
 
   index that should be executed or -1 if no entry should be executed (e.g.,
366
 
   Esc pressed to exit a sub-menu or switching menu viewers).
367
 
   If the return value is not -1, then *AUTO_BOOT is nonzero iff the menu
368
 
   entry to be executed is a result of an automatic default selection because
369
 
   of the timeout.  */
370
 
static int
371
 
run_menu (grub_menu_t menu, int nested, int *auto_boot)
372
 
{
373
 
  grub_uint64_t saved_time;
374
 
  int default_entry, current_entry;
375
 
  int timeout;
376
 
 
377
 
  default_entry = get_entry_number (menu, "default");
378
 
 
379
 
  /* If DEFAULT_ENTRY is not within the menu entries, fall back to
380
 
     the first entry.  */
381
 
  if (default_entry < 0 || default_entry >= menu->size)
382
 
    default_entry = 0;
383
 
 
384
 
  /* If timeout is 0, drawing is pointless (and ugly).  */
385
 
  if (grub_menu_get_timeout () == 0)
386
 
    {
387
 
      *auto_boot = 1;
388
 
      return default_entry;
389
 
    }
390
 
 
391
 
  current_entry = default_entry;
392
 
 
393
 
  /* Initialize the time.  */
394
 
  saved_time = grub_get_time_ms ();
395
 
 
396
 
 refresh:
397
 
  menu_init (current_entry, menu, nested);
398
 
 
399
 
  timeout = grub_menu_get_timeout ();
400
 
 
401
 
  if (timeout > 0)
402
 
    menu_print_timeout (timeout);
403
 
  else
404
 
    clear_timeout ();
405
 
 
406
 
  while (1)
407
 
    {
408
 
      int c;
409
 
      timeout = grub_menu_get_timeout ();
410
 
 
411
 
      if (grub_normal_exit_level)
412
 
        return -1;
413
 
 
414
 
      if (timeout > 0)
415
 
        {
416
 
          grub_uint64_t current_time;
417
 
 
418
 
          current_time = grub_get_time_ms ();
419
 
          if (current_time - saved_time >= 1000)
420
 
            {
421
 
              timeout--;
422
 
              grub_menu_set_timeout (timeout);
423
 
              saved_time = current_time;
424
 
              menu_print_timeout (timeout);
425
 
            }
426
 
        }
427
 
 
428
 
      if (timeout == 0)
429
 
        {
430
 
          grub_env_unset ("timeout");
431
 
          *auto_boot = 1;
432
 
          menu_fini ();
433
 
          return default_entry;
434
 
        }
435
 
 
436
 
      if (grub_checkkey () >= 0 || timeout < 0)
437
 
        {
438
 
          c = GRUB_TERM_ASCII_CHAR (grub_getkey ());
439
 
 
440
 
          if (timeout >= 0)
441
 
            {
442
 
              grub_env_unset ("timeout");
443
 
              grub_env_unset ("fallback");
444
 
              clear_timeout ();
445
 
            }
446
 
 
447
 
          switch (c)
448
 
            {
449
 
            case GRUB_TERM_HOME:
450
 
              current_entry = 0;
451
 
              menu_set_chosen_entry (current_entry);
452
 
              break;
453
 
 
454
 
            case GRUB_TERM_END:
455
 
              current_entry = menu->size - 1;
456
 
              menu_set_chosen_entry (current_entry);
457
 
              break;
458
 
 
459
 
            case GRUB_TERM_UP:
460
 
            case '^':
461
 
              if (current_entry > 0)
462
 
                current_entry--;
463
 
              menu_set_chosen_entry (current_entry);
464
 
              break;
465
 
 
466
 
            case GRUB_TERM_DOWN:
467
 
            case 'v':
468
 
              if (current_entry < menu->size - 1)
469
 
                current_entry++;
470
 
              menu_set_chosen_entry (current_entry);
471
 
              break;
472
 
 
473
 
            case GRUB_TERM_PPAGE:
474
 
              if (current_entry < GRUB_MENU_PAGE_SIZE)
475
 
                current_entry = 0;
476
 
              else
477
 
                current_entry -= GRUB_MENU_PAGE_SIZE;
478
 
              menu_set_chosen_entry (current_entry);
479
 
              break;
480
 
 
481
 
            case GRUB_TERM_NPAGE:
482
 
              if (current_entry + GRUB_MENU_PAGE_SIZE < menu->size)
483
 
                current_entry += GRUB_MENU_PAGE_SIZE;
484
 
              else
485
 
                current_entry = menu->size - 1;
486
 
              menu_set_chosen_entry (current_entry);
487
 
              break;
488
 
 
489
 
            case '\n':
490
 
            case '\r':
491
 
            case 6:
492
 
              menu_fini ();
493
 
              *auto_boot = 0;
494
 
              return current_entry;
495
 
 
496
 
            case '\e':
497
 
              if (nested)
498
 
                {
499
 
                  menu_fini ();
500
 
                  return -1;
501
 
                }
502
 
              break;
503
 
 
504
 
            case 'c':
505
 
              menu_fini ();
506
 
              grub_cmdline_run (1);
507
 
              goto refresh;
508
 
 
509
 
            case 'e':
510
 
              menu_fini ();
511
 
                {
512
 
                  grub_menu_entry_t e = grub_menu_get_entry (menu, current_entry);
513
 
                  if (e)
514
 
                    grub_menu_entry_run (e);
515
 
                }
516
 
              goto refresh;
517
 
 
518
 
            default:
519
 
              {
520
 
                grub_menu_entry_t entry;
521
 
                int i;
522
 
                for (i = 0, entry = menu->entry_list; i < menu->size;
523
 
                     i++, entry = entry->next)
524
 
                  if (entry->hotkey == c)
525
 
                    {
526
 
                      menu_fini ();
527
 
                      *auto_boot = 0;
528
 
                      return i;
529
 
                    }
530
 
              }
531
 
              break;
532
 
            }
533
 
        }
534
 
    }
535
 
 
536
 
  /* Never reach here.  */
537
 
  return -1;
538
 
}
539
 
 
540
 
/* Callback invoked immediately before a menu entry is executed.  */
541
 
static void
542
 
notify_booting (grub_menu_entry_t entry,
543
 
                void *userdata __attribute__((unused)))
544
 
{
545
 
  grub_printf ("  ");
546
 
  grub_printf_ (N_("Booting \'%s\'"), entry->title);
547
 
  grub_printf ("\n\n");
548
 
}
549
 
 
550
 
/* Callback invoked when a default menu entry executed because of a timeout
551
 
   has failed and an attempt will be made to execute the next fallback
552
 
   entry, ENTRY.  */
553
 
static void
554
 
notify_fallback (grub_menu_entry_t entry,
555
 
                 void *userdata __attribute__((unused)))
556
 
{
557
 
  grub_printf ("\n   ");
558
 
  grub_printf_ (N_("Falling back to \'%s\'"), entry->title);
559
 
  grub_printf ("\n\n");
560
 
  grub_millisleep (DEFAULT_ENTRY_ERROR_DELAY_MS);
561
 
}
562
 
 
563
 
/* Callback invoked when a menu entry has failed and there is no remaining
564
 
   fallback entry to attempt.  */
565
 
static void
566
 
notify_execution_failure (void *userdata __attribute__((unused)))
567
 
{
568
 
  if (grub_errno != GRUB_ERR_NONE)
569
 
    {
570
 
      grub_print_error ();
571
 
      grub_errno = GRUB_ERR_NONE;
572
 
    }
573
 
  grub_printf ("\n  ");
574
 
  grub_printf_ (N_("Failed to boot both default and fallback entries.\n"));
575
 
  grub_wait_after_message ();
576
 
}
577
 
 
578
 
/* Callbacks used by the text menu to provide user feedback when menu entries
579
 
   are executed.  */
580
 
static struct grub_menu_execute_callback execution_callback =
581
 
{
582
 
  .notify_booting = notify_booting,
583
 
  .notify_fallback = notify_fallback,
584
 
  .notify_failure = notify_execution_failure
585
 
};
586
 
 
587
 
static grub_err_t
588
 
show_menu (grub_menu_t menu, int nested)
589
 
{
590
 
  while (1)
591
 
    {
592
 
      int boot_entry;
593
 
      grub_menu_entry_t e;
594
 
      int auto_boot;
595
 
 
596
 
      boot_entry = run_menu (menu, nested, &auto_boot);
597
 
      if (boot_entry < 0)
598
 
        break;
599
 
 
600
 
      e = grub_menu_get_entry (menu, boot_entry);
601
 
      if (! e)
602
 
        continue; /* Menu is empty.  */
603
 
 
604
 
      grub_cls ();
605
 
 
606
 
      if (auto_boot)
607
 
        {
608
 
          grub_menu_execute_with_fallback (menu, e, &execution_callback, 0);
609
 
        }
610
 
      else
611
 
        {
612
 
          int chars_before = grub_normal_get_char_counter ();
613
 
          grub_errno = GRUB_ERR_NONE;
614
 
          grub_menu_execute_entry (e);
615
 
          grub_print_error ();
616
 
          grub_errno = GRUB_ERR_NONE;
617
 
 
618
 
          if (chars_before != grub_normal_get_char_counter ())
619
 
            grub_wait_after_message ();
620
 
        }
621
 
    }
622
 
 
623
 
  return GRUB_ERR_NONE;
624
 
}
625
 
 
626
 
grub_err_t
627
 
grub_show_menu (grub_menu_t menu, int nested)
628
 
{
629
 
  grub_err_t err1, err2;
630
 
 
631
 
  while (1)
632
 
    {
633
 
      err1 = show_menu (menu, nested);
634
 
      grub_print_error ();
635
 
 
636
 
      if (grub_normal_exit_level)
637
 
        break;
638
 
 
639
 
      err2 = grub_auth_check_authentication (NULL);
640
 
      if (err2)
641
 
        {
642
 
          grub_print_error ();
643
 
          grub_errno = GRUB_ERR_NONE;
644
 
          continue;
645
 
        }
646
 
 
647
 
      break;
648
 
    }
649
 
 
650
 
  return err1;
651
 
}