/*++ Copyright (c) 2000 Microsoft Corporation Module Name: menu.c Abstract: Revision History: Jeff Sigman 05/01/00 Created Jeff Sigman 05/10/00 Version 1.5 released Jeff Sigman 10/18/00 Fix for Soft81 bug(s) --*/ #include "precomp.h" ADVANCEDBOOT_OPTIONS AdvancedBootOptions[] = { {BL_MENU_ITEM, BL_SAFEBOOT_OPTION1, BL_SAFEBOOT_OPTION1M}, {BL_MENU_ITEM, BL_SAFEBOOT_OPTION2, BL_SAFEBOOT_OPTION2M}, {BL_MENU_ITEM, BL_SAFEBOOT_OPTION4, BL_SAFEBOOT_OPTION4M}, {BL_MENU_BLANK_LINE, NULL, NULL}, {BL_MENU_ITEM, BL_BOOTLOG, BL_BOOTLOGM}, {BL_MENU_ITEM, BL_BASEVIDEO, BL_BASEVIDEOM}, {BL_MENU_ITEM, BL_LASTKNOWNGOOD_OPTION, NULL}, {BL_MENU_ITEM, BL_SAFEBOOT_OPTION6, BL_SAFEBOOT_OPTION6M}, {BL_MENU_ITEM, BL_DEBUG_OPTION, BL_DEBUG_OPTIONM}, {BL_MENU_BLANK_LINE, NULL, NULL}, {BL_MENU_ITEM, BL_MSG_BOOT_NORMALLY, NULL}, {BL_MENU_ITEM, BL_MSG_OSCHOICES_MENU, NULL} }; #define MaxAdvancedBootOptions (sizeof(AdvancedBootOptions)/sizeof(ADVANCEDBOOT_OPTIONS)) // // // char* FindAdvLoadOptions( IN char* String ) { char* find = NULL; UINTN i; for (i = 0; i < MaxAdvancedBootOptions; i++) { if (!AdvancedBootOptions[i].LoadOptions) { continue; } if (find = strstr(String, AdvancedBootOptions[i].LoadOptions)) { if (*(find - 1) == SPACEC) { find--; break; } else { find = NULL; continue; } } } return find; } // // // void MenuEraseLine( IN UINTN x, IN UINTN y, IN UINTN* Width ) { UINTN i; ST->ConOut->SetCursorPosition(ST->ConOut, x, y); for (i = 0; i < *Width; i++) { Print(L" "); } ST->ConOut->SetCursorPosition(ST->ConOut, x, y); return; } // // // void MenuHighlightOn( ) { ST->ConOut->SetAttribute(ST->ConOut, EFI_BACKGROUND_LIGHTGRAY); return; } // // // void MenuHighlightOff( ) { ST->ConOut->SetAttribute(ST->ConOut, EFI_TEXT_ATTR(EFI_LIGHTGRAY, EFI_BLACK)); ST->ConOut->SetAttribute(ST->ConOut, EFI_BACKGROUND_BLACK); return; } // // // void MenuHighlight( IN UINTN Flag, IN UINTN* Highlight, IN UINTN* Width, IN UINT16 Key, IN VOID* hBootData ) { BOOT_DATA* pBootData = (BOOT_DATA*) hBootData; do { if (Flag == HIGHLT_MAIN_INIT) { MenuHighlightOn(); Print(L" %a (%a)\n", pBootData->pszIdent[*Highlight], pBootData->pszShort[*Highlight]); MenuHighlightOff(); break; } else if (Flag == HIGHLT_MAIN_LOOP) { MenuEraseLine(0, (*Highlight) + 5, Width); Print(L" %a (%a)\n", pBootData->pszIdent[*Highlight], pBootData->pszShort[*Highlight]); switch (Key) { case SCAN_UP: if (*Highlight == 0) { *Highlight = pBootData->dwIndex; } else { (*Highlight)--; } break; case SCAN_DOWN: if (*Highlight == pBootData->dwIndex) { *Highlight = 0; } else { (*Highlight)++; } break; } MenuEraseLine(0, (*Highlight) + 5, Width); MenuHighlightOn(); Print(L" %a (%a)\n", pBootData->pszIdent[*Highlight], pBootData->pszShort[*Highlight]); MenuHighlightOff(); break; } else if (Flag == HIGHLT_ADVND_INIT) { MenuHighlightOn(); Print(L" %s\n", AdvancedBootOptions[*Highlight].MsgId); MenuHighlightOff(); break; } else if (Flag == HIGHLT_ADVND_LOOP) { MenuEraseLine(0, (*Highlight) + 4, Width); Print(L" %s\n", AdvancedBootOptions[*Highlight].MsgId); switch (Key) { case SCAN_UP: if (*Highlight == 0) { *Highlight = MaxAdvancedBootOptions - 1; } else { (*Highlight)--; } // // Check for space // if (AdvancedBootOptions[*Highlight].MsgId == NULL) { if (*Highlight == 0) { *Highlight = MaxAdvancedBootOptions - 1; } else { (*Highlight)--; } } break; case SCAN_DOWN: if (*Highlight == MaxAdvancedBootOptions - 1) { *Highlight =0; } else { (*Highlight)++; } // // Check for space // if (AdvancedBootOptions[*Highlight].MsgId == NULL) { if (*Highlight == MaxAdvancedBootOptions - 1) { *Highlight = 0; } else { (*Highlight)++; } } break; } MenuEraseLine(0, (*Highlight) + 4, Width); MenuHighlightOn(); Print(L" %s\n", AdvancedBootOptions[*Highlight].MsgId); MenuHighlightOff(); break; } } while (FALSE); return; } // // // UINTN DrawAdvancedBoot( IN UINTN* Width, IN VOID* hBootData ) { UINTN i, Highlight = 0, Exit = 0; BOOT_DATA* pBootData = (BOOT_DATA*) hBootData; EFI_INPUT_KEY Key; // // Clear the screen // ST->ConOut->ClearScreen(ST->ConOut); Print(L"\n%s\n\n", BL_ADVANCEDBOOT_TITLE); for (i = 0; i < MaxAdvancedBootOptions; i++) { if (i == Highlight) { MenuHighlight(HIGHLT_ADVND_INIT, &Highlight, NULL, 0, pBootData); continue; } if (!(AdvancedBootOptions[i].MsgId)) { Print(L"\n"); continue; } Print(L" %s\n", AdvancedBootOptions[i].MsgId); } Print(L"\n%s%c%s%c%s\n", BL_MOVE_HIGHLIGHT1, ARROW_UP, BL_MOVE_HIGHLIGHT2, ARROW_DOWN, BL_MOVE_HIGHLIGHT3); // // Loop through menu options until user hits enter/esc // while (!Exit) { WaitForSingleEvent(ST->ConIn->WaitForKey, 0); ST->ConIn->ReadKeyStroke(ST->ConIn, &Key); switch (Key.UnicodeChar) { case CHAR_CARRIAGE_RETURN: Exit = 1; continue; case 0: switch (Key.ScanCode) { case SCAN_UP: MenuHighlight( HIGHLT_ADVND_LOOP, &Highlight, Width, SCAN_UP, pBootData); break; case SCAN_DOWN: MenuHighlight( HIGHLT_ADVND_LOOP, &Highlight, Width, SCAN_DOWN, pBootData); break; case SCAN_ESC: Highlight = 11; Exit = 1; continue; } } } return Highlight; } // // // void DrawChoices( IN UINTN* Highlight, IN VOID* hBootData ) { int i; BOOT_DATA* pBootData = (BOOT_DATA*) hBootData; // // Clear the screen // ST->ConOut->ClearScreen(ST->ConOut); Print(L"\n\n%s\n\n\n", BL_SELECT_OS); for (i = 0; i <= pBootData->dwIndex; i++) { if (*Highlight == i) { MenuHighlight(HIGHLT_MAIN_INIT, Highlight, NULL, 0, pBootData); continue; } Print(L" %a (%a)\n", pBootData->pszIdent[i], pBootData->pszShort[i]); } Print(L"\n%s%c%s%c%s\n", BL_MOVE_HIGHLIGHT1, ARROW_UP, BL_MOVE_HIGHLIGHT2, ARROW_DOWN, BL_MOVE_HIGHLIGHT3); return; } // // // void EnableAdvOpt( IN VOID* hBootData, IN UINTN* Index ) { BOOT_DATA* pBootData = (BOOT_DATA*) hBootData; if (AdvancedBootOptions[*Index].LoadOptions) { pBootData->pszLoadOpt = RutlStrDup(AdvancedBootOptions[*Index].LoadOptions); } else { pBootData->dwLastKnown = 1; } return; } // // // void DisableAdvOpt( IN VOID* hBootData ) { BOOT_DATA* pBootData = (BOOT_DATA*) hBootData; if (pBootData->pszLoadOpt) pBootData->pszLoadOpt = RutlFree(pBootData->pszLoadOpt); pBootData->dwLastKnown = 0; return; } // // // UINTN DisplayMenu( IN VOID* hBootData ) { int i; UINTN j, Highlight = 0, Width = 0, Height = 0, Exit = 0, Advanced = 0; BOOT_DATA* pBootData = (BOOT_DATA*) hBootData; EFI_STATUS Status; EFI_INPUT_KEY Key; // // Set the screen to 80 x 25 mode // ST->ConOut->SetMode(ST->ConOut, 0); // // Get the height and width of the screen // ST->ConOut->QueryMode(ST->ConOut, ST->ConOut->Mode->Mode, &Width, &Height); // // Disable the cursor // ST->ConOut->EnableCursor(ST->ConOut, FALSE); DrawChoices(&Highlight, pBootData); Print(L"%s", BL_TIMEOUT_COUNTDOWN); for (i = (int)pBootData->dwCount; i >= 0; i--) { Print(L"\n\n\n%s", BL_ADVANCED_BOOT_MESSAGE); ST->ConOut->SetCursorPosition( ST->ConOut, StrLen(BL_TIMEOUT_COUNTDOWN), BL_NUMBER_OF_LINES + pBootData->dwIndex - 1); Print(L"%d ", i); // // Wait 1 second, stop waiting if a key is pressed // Status = WaitForSingleEvent(ST->ConIn->WaitForKey, 10000000); // // Get the key from the buffer // ST->ConIn->ReadKeyStroke(ST->ConIn, &Key); if (Status == EFI_TIMEOUT) { Exit = 1; continue; } else { Exit = 0; // // Erase the the timeout message // MenuEraseLine( 0, BL_NUMBER_OF_LINES + pBootData->dwIndex - 1, &Width); break; } } // // Loop through menu options until user hits enter // while (!Exit) { switch (Key.UnicodeChar) { case CHAR_CARRIAGE_RETURN: Exit = 1; continue; case 0: switch (Key.ScanCode) { case SCAN_UP: MenuHighlight( HIGHLT_MAIN_LOOP, &Highlight, &Width, SCAN_UP, pBootData); break; case SCAN_DOWN: MenuHighlight( HIGHLT_MAIN_LOOP, &Highlight, &Width, SCAN_DOWN, pBootData); break; case SCAN_F8: Advanced = DrawAdvancedBoot(&Width, pBootData); // // If user already selected another option, we kill it // DisableAdvOpt(pBootData); if (Advanced == 10) { Exit = 1; continue; } else { DrawChoices(&Highlight, pBootData); Print(L"\n\n\n%s", BL_ADVANCED_BOOT_MESSAGE); if (Advanced < 9) { EnableAdvOpt(pBootData, &Advanced); ST->ConOut->SetAttribute(ST->ConOut, EFI_TEXT_ATTR(EFI_LIGHTBLUE, EFI_BLACK)); Print(L"\n\n%s", AdvancedBootOptions[Advanced].MsgId); MenuHighlightOff(); break; } } break; } } WaitForSingleEvent(ST->ConIn->WaitForKey, 0); ST->ConIn->ReadKeyStroke(ST->ConIn, &Key); } // // Clear the screen // ST->ConOut->ClearScreen(ST->ConOut); // // Re-enable the cursor // ST->ConOut->EnableCursor(ST->ConOut, TRUE); return Highlight; }