📄 stage2.c
字号:
/* * GRUB -- GRand Unified Bootloader * Copyright (C) 2000,2001,2002,2004 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <shared.h>#include <term.h>grub_jmp_buf restart_env;#if defined(PRESET_MENU_STRING) || defined(SUPPORT_DISKLESS)# if defined(PRESET_MENU_STRING)static const char *preset_menu = PRESET_MENU_STRING;# elif defined(SUPPORT_DISKLESS)/* Execute the command "bootp" automatically. */static const char *preset_menu = "bootp\n";# endif /* SUPPORT_DISKLESS */static int preset_menu_offset;static intopen_preset_menu (void){#ifdef GRUB_UTIL /* Unless the user explicitly requests to use the preset menu, always opening the preset menu fails in the grub shell. */ if (! use_preset_menu) return 0;#endif /* GRUB_UTIL */ preset_menu_offset = 0; return preset_menu != 0;}static intread_from_preset_menu (char *buf, int maxlen){ int len = grub_strlen (preset_menu + preset_menu_offset); if (len > maxlen) len = maxlen; grub_memmove (buf, preset_menu + preset_menu_offset, len); preset_menu_offset += len; return len;}static voidclose_preset_menu (void){ /* Disable the preset menu. */ preset_menu = 0;}#else /* ! PRESET_MENU_STRING && ! SUPPORT_DISKLESS */#define open_preset_menu() 0#define read_from_preset_menu(buf, maxlen) 0#define close_preset_menu()#endif /* ! PRESET_MENU_STRING && ! SUPPORT_DISKLESS */static char *get_entry (char *list, int num, int nested){ int i; for (i = 0; i < num; i++) { do { while (*(list++)); } while (nested && *(list++)); } return list;}/* Print an entry in a line of the menu box. */static voidprint_entry (int y, int highlight, char *entry){ int x; if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_NORMAL); if (highlight && current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_HIGHLIGHT); gotoxy (2, y); grub_putchar (' '); for (x = 3; x < 75; x++) { if (*entry && x <= 72) { if (x == 72) grub_putchar (DISP_RIGHT); else grub_putchar (*entry++); } else grub_putchar (' '); } gotoxy (74, y); if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_STANDARD);}/* Print entries in the menu box. */static voidprint_entries (int y, int size, int first, int entryno, char *menu_entries){ int i; gotoxy (77, y + 1); if (first) grub_putchar (DISP_UP); else grub_putchar (' '); menu_entries = get_entry (menu_entries, first, 0); for (i = 0; i < size; i++) { print_entry (y + i + 1, entryno == i, menu_entries); while (*menu_entries) menu_entries++; if (*(menu_entries - 1)) menu_entries++; } gotoxy (77, y + size); if (*menu_entries) grub_putchar (DISP_DOWN); else grub_putchar (' '); gotoxy (74, y + entryno + 1);}static voidprint_entries_raw (int size, int first, char *menu_entries){ int i;#define LINE_LENGTH 67 for (i = 0; i < LINE_LENGTH; i++) grub_putchar ('-'); grub_putchar ('\n'); for (i = first; i < size; i++) { /* grub's printf can't %02d so ... */ if (i < 10) grub_putchar (' '); grub_printf ("%d: %s\n", i, get_entry (menu_entries, i, 0)); } for (i = 0; i < LINE_LENGTH; i++) grub_putchar ('-'); grub_putchar ('\n');#undef LINE_LENGTH}static voidprint_border (int y, int size){ int i; if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_NORMAL); gotoxy (1, y); grub_putchar (DISP_UL); for (i = 0; i < 73; i++) grub_putchar (DISP_HORIZ); grub_putchar (DISP_UR); i = 1; while (1) { gotoxy (1, y + i); if (i > size) break; grub_putchar (DISP_VERT); gotoxy (75, y + i); grub_putchar (DISP_VERT); i++; } grub_putchar (DISP_LL); for (i = 0; i < 73; i++) grub_putchar (DISP_HORIZ); grub_putchar (DISP_LR); if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_STANDARD);}static voidrun_menu (char *menu_entries, char *config_entries, int num_entries, char *heap, int entryno){ int c, time1, time2 = -1, first_entry = 0; char *cur_entry = 0; /* * Main loop for menu UI. */restart: /* Dumb terminal always use all entries for display invariant for TERM_DUMB: first_entry == 0 */ if (! (current_term->flags & TERM_DUMB)) { while (entryno > 11) { first_entry++; entryno--; } } /* If the timeout was expired or wasn't set, force to show the menu interface. */ if (grub_timeout < 0) show_menu = 1; /* If SHOW_MENU is false, don't display the menu until ESC is pressed. */ if (! show_menu) { /* Get current time. */ while ((time1 = getrtsecs ()) == 0xFF) ; while (1) { /* Check if ESC is pressed. */ if (checkkey () != -1 && ASCII_CHAR (getkey ()) == '\e') { grub_timeout = -1; show_menu = 1; break; } /* If GRUB_TIMEOUT is expired, boot the default entry. */ if (grub_timeout >=0 && (time1 = getrtsecs ()) != time2 && time1 != 0xFF) { if (grub_timeout <= 0) { grub_timeout = -1; goto boot_entry; } time2 = time1; grub_timeout--; /* Print a message. */ grub_printf ("\rPress `ESC' to enter the menu... %d ", grub_timeout); } } } /* Only display the menu if the user wants to see it. */ if (show_menu) { init_page (); setcursor (0); if (current_term->flags & TERM_DUMB) print_entries_raw (num_entries, first_entry, menu_entries); else print_border (3, 12); grub_printf ("\n\ Use the %c and %c keys to select which entry is highlighted.\n", DISP_UP, DISP_DOWN); if (! auth && password) { printf ("\ Press enter to boot the selected OS or \'p\' to enter a\n\ password to unlock the next set of features."); } else { if (config_entries) printf ("\ Press enter to boot the selected OS, \'e\' to edit the\n\ commands before booting, or \'c\' for a command-line."); else printf ("\ Press \'b\' to boot, \'e\' to edit the selected command in the\n\ boot sequence, \'c\' for a command-line, \'o\' to open a new line\n\ after (\'O\' for before) the selected line, \'d\' to remove the\n\ selected line, or escape to go back to the main menu."); } if (current_term->flags & TERM_DUMB) grub_printf ("\n\nThe selected entry is %d ", entryno); else print_entries (3, 12, first_entry, entryno, menu_entries); } /* XX using RT clock now, need to initialize value */ while ((time1 = getrtsecs()) == 0xFF); while (1) { /* Initialize to NULL just in case... */ cur_entry = NULL; if (grub_timeout >= 0 && (time1 = getrtsecs()) != time2 && time1 != 0xFF) { if (grub_timeout <= 0) { grub_timeout = -1; break; } /* else not booting yet! */ time2 = time1; if (current_term->flags & TERM_DUMB) grub_printf ("\r Entry %d will be booted automatically in %d seconds. ", entryno, grub_timeout); else { gotoxy (3, 22); grub_printf ("The highlighted entry will be booted automatically in %d seconds. ", grub_timeout); gotoxy (74, 4 + entryno); } grub_timeout--; } /* Check for a keypress, however if TIMEOUT has been expired (GRUB_TIMEOUT == -1) relax in GETKEY even if no key has been pressed. This avoids polling (relevant in the grub-shell and later on in grub if interrupt driven I/O is done). */ if (checkkey () >= 0 || grub_timeout < 0) { /* Key was pressed, show which entry is selected before GETKEY, since we're comming in here also on GRUB_TIMEOUT == -1 and hang in GETKEY */ if (current_term->flags & TERM_DUMB) grub_printf ("\r Highlighted entry is %d: ", entryno); c = ASCII_CHAR (getkey ()); if (grub_timeout >= 0) { if (current_term->flags & TERM_DUMB) grub_putchar ('\r'); else gotoxy (3, 22); printf (" "); grub_timeout = -1; fallback_entry = -1; if (! (current_term->flags & TERM_DUMB)) gotoxy (74, 4 + entryno); } /* We told them above (at least in SUPPORT_SERIAL) to use '^' or 'v' so accept these keys. */ if (c == 16 || c == '^') { if (current_term->flags & TERM_DUMB) { if (entryno > 0) entryno--; } else { if (entryno > 0) { print_entry (4 + entryno, 0, get_entry (menu_entries, first_entry + entryno, 0)); entryno--; print_entry (4 + entryno, 1, get_entry (menu_entries, first_entry + entryno, 0)); } else if (first_entry > 0) { first_entry--; print_entries (3, 12, first_entry, entryno, menu_entries); } } } else if ((c == 14 || c == 'v') && first_entry + entryno + 1 < num_entries) { if (current_term->flags & TERM_DUMB) entryno++; else { if (entryno < 11) { print_entry (4 + entryno, 0, get_entry (menu_entries, first_entry + entryno, 0)); entryno++; print_entry (4 + entryno, 1, get_entry (menu_entries, first_entry + entryno, 0)); } else if (num_entries > 12 + first_entry) { first_entry++; print_entries (3, 12, first_entry, entryno, menu_entries); } } } else if (c == 7) { /* Page Up */ first_entry -= 12; if (first_entry < 0) { entryno += first_entry; first_entry = 0; if (entryno < 0) entryno = 0; } print_entries (3, 12, first_entry, entryno, menu_entries); } else if (c == 3) { /* Page Down */ first_entry += 12; if (first_entry + entryno + 1 >= num_entries) { first_entry = num_entries - 12; if (first_entry < 0) first_entry = 0; entryno = num_entries - first_entry - 1; } print_entries (3, 12, first_entry, entryno, menu_entries); } if (config_entries) { if ((c == '\n') || (c == '\r') || (c == 6)) break; } else { if ((c == 'd') || (c == 'o') || (c == 'O')) { if (! (current_term->flags & TERM_DUMB)) print_entry (4 + entryno, 0, get_entry (menu_entries, first_entry + entryno, 0)); /* insert after is almost exactly like insert before */ if (c == 'o') { /* But `o' differs from `O', since it may causes the menu screen to scroll up. */ if (entryno < 11 || (current_term->flags & TERM_DUMB)) entryno++; else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -