📄 stage2.c
字号:
/* * GRUB -- GRand Unified Bootloader * Copyright (C) 2000,2001,2002,2004,2005 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>#ifdef SUPPORT_GRAPHICSextern int disable_space_highlight;#endif /* SUPPORT_GRAPHICS */#ifdef GRUB_UTILgrub_jmp_buf restart_env;/* The preset_menu variable is referenced by asm.S */# if defined(PRESET_MENU_STRING)const char *preset_menu = PRESET_MENU_STRING;# elif defined(SUPPORT_DISKLESS)/* Execute the command "bootp" automatically. */const char *preset_menu = "bootp\n";#else /* ! SUPPORT_DISKLESS *//* The preset_menu variable is always available. This is for the loader, which * loads GRUB, to define a new preset menu before transferring control to GRUB. */const char *preset_menu = 0;# endif /* ! SUPPORT_DISKLESS */#else /* ! GRUB_UTIL *//* preset_menu is defined in asm.S */#endif /* GRUB_UTIL */#if 1 || defined(PRESET_MENU_STRING) || defined(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 max_len){ int len; if (preset_menu == 0) return 0; len = grub_strlen (preset_menu + preset_menu_offset); if (len > max_len) len = max_len; 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, max_len) 0#define close_preset_menu()#endif /* ! PRESET_MENU_STRING && ! SUPPORT_DISKLESS */#ifdef GRUB_UTIL#undef DISP_UL //218#undef DISP_UR //191#undef DISP_LL //192#undef DISP_LR //217#undef DISP_HORIZ //196#undef DISP_VERT //179#undef DISP_LEFT //0x1b#undef DISP_RIGHT //0x1a#undef DISP_UP //0x18#undef DISP_DOWN //0x19#define DISP_UL ACS_ULCORNER /* 0xDA , '+' */#define DISP_UR ACS_URCORNER /* 0xBF , '+' */#define DISP_LL ACS_LLCORNER /* 0xC0 , '+' */#define DISP_LR ACS_LRCORNER /* 0xD9 , '+' */#define DISP_HORIZ ACS_HLINE /* 0xC4 , '-' */#define DISP_VERT ACS_VLINE /* 0xB3 , '|' */#define DISP_LEFT ACS_LARROW /* 0x1B , '<' */#define DISP_RIGHT ACS_RARROW /* 0x1A , '>' */#define DISP_UP ACS_UARROW /* 0x18 , '^' */#define DISP_DOWN ACS_DARROW /* 0x19 , 'v' */#endif/* line start */#define MENU_BOX_X 2/* line width */#define MENU_BOX_W 76/* first line number */#define MENU_BOX_Y 2/* window height */#define MENU_BOX_H (current_term->max_lines - 8)/* line end */#define MENU_BOX_E (MENU_BOX_X + MENU_BOX_W)/* window bottom */#define MENU_BOX_B (MENU_BOX_Y + MENU_BOX_H)static long temp_entryno;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 (highlight ? COLOR_STATE_HIGHLIGHT : COLOR_STATE_NORMAL); // if (highlight && current_term->setcolorstate)// current_term->setcolorstate (COLOR_STATE_HIGHLIGHT); gotoxy (MENU_BOX_X - 1, y);#ifdef SUPPORT_GRAPHICS disable_space_highlight = 1;#endif /* SUPPORT_GRAPHICS */ grub_putchar (' ');#ifdef SUPPORT_GRAPHICS disable_space_highlight = 0;#endif /* SUPPORT_GRAPHICS */ for (x = MENU_BOX_X; x < MENU_BOX_E; x++) { if (*entry && x <= MENU_BOX_W) { if (x == MENU_BOX_W) grub_putchar (DISP_RIGHT); else grub_putchar (*entry++); } else {#ifdef SUPPORT_GRAPHICS disable_space_highlight = 1;#endif /* SUPPORT_GRAPHICS */ grub_putchar (' '); } }#ifdef SUPPORT_GRAPHICS disable_space_highlight = 0;#endif /* SUPPORT_GRAPHICS */ //gotoxy (MENU_BOX_E - 1, y); /* XXX: Why? */ if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_STANDARD);}/* Print entries in the menu box. */static voidprint_entries (int first, int entryno, char *menu_entries){ int i; if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_NORMAL); gotoxy (MENU_BOX_E, MENU_BOX_Y); if (first) grub_putchar (DISP_UP); else grub_putchar (DISP_VERT); menu_entries = get_entry (menu_entries, first, 0); for (i = 0; i < MENU_BOX_H/*size*/; i++) { print_entry (MENU_BOX_Y + i, entryno == i, menu_entries); while (*menu_entries) menu_entries++; if (*(menu_entries - 1)) menu_entries++; } gotoxy (MENU_BOX_E, MENU_BOX_Y - 1 + MENU_BOX_H/*size*/); if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_NORMAL); if (*menu_entries) grub_putchar (DISP_DOWN); else grub_putchar (DISP_VERT); if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_STANDARD); gotoxy (MENU_BOX_E, MENU_BOX_Y + entryno); /* XXX: Why? */}static voidprint_entries_raw (int size, int first, char *menu_entries){ int i; for (i = 0; i < MENU_BOX_W; 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 < MENU_BOX_W; i++) grub_putchar ('-'); grub_putchar ('\n');}static voidprint_border (int y, int size){ int i; if (current_term->setcolorstate) current_term->setcolorstate (COLOR_STATE_NORMAL); gotoxy (MENU_BOX_X - 2, y); grub_putchar (DISP_UL); for (i = 0; i < MENU_BOX_W + 1; i++) grub_putchar (DISP_HORIZ); grub_putchar (DISP_UR); i = 1; while (1) { gotoxy (MENU_BOX_X - 2, y + i); if (i > size) break; grub_putchar (DISP_VERT); gotoxy (MENU_BOX_E, y + i); grub_putchar (DISP_VERT); i++; } grub_putchar (DISP_LL); for (i = 0; i < MENU_BOX_W + 1; 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;// struct term_entry *prev_term = NULL; /* * 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)) {#if 0 while (entryno > 11) { first_entry++; entryno--; }#else if (entryno > MENU_BOX_H - 1) { first_entry += entryno - (MENU_BOX_H - 1); entryno = MENU_BOX_H - 1; }#endif } /* 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 (MENU_BOX_Y - 1, MENU_BOX_H); grub_printf ("\nUse the %c and %c keys to highlight an entry.", DISP_UP, DISP_DOWN); if (! auth && password) { printf (" Press ENTER or \'b\' to boot.\n" "Press \'p\' to gain privileged control."); } else { if (config_entries) printf (" Press ENTER or \'b\' to boot.\n" "Press \'e\' to edit the commands before booting, or \'c\' for a command-line."); else printf (" At a selected line, press \'e\' to\n" "edit, \'d\' to delete, or \'O\'/\'o\' to open a new line before/after. When done,\n" "press \'b\' to boot, \'c\' for a command-line, or ESC 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 (first_entry, entryno, menu_entries); } /* XX using RT clock now, need to initialize value */ while ((time1 = getrtsecs()) == 0xFF); temp_entryno = 0; 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 (MENU_BOX_X - 2, MENU_BOX_H + 7); grub_printf ("The highlighted entry will be booted automatically in %d seconds. ", grub_timeout); gotoxy (MENU_BOX_E, MENU_BOX_Y + 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 (MENU_BOX_X - 2, MENU_BOX_H + 7); printf (" "); grub_timeout = -1; fallback_entryno = -1; if (! (current_term->flags & TERM_DUMB)) gotoxy (MENU_BOX_E, MENU_BOX_Y + entryno); } /* We told them above (at least in SUPPORT_SERIAL) to use '^' or 'v' so accept these keys. */ if (c == KEY_UP/*16*/ || ((char)c) == '^')
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -