boot.c

来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 1,972 行 · 第 1/5 页

C
1,972
字号
        AllocateSpecialBootOption (&BootMenu, L"Delete All Boot Options", CON_UNSELECTED, DELETE_MENU_ALL);
    SaveNvramContext =
        AllocateSpecialBootOption (&BootMenu, L"Save Settings to NVRAM", CON_UNSELECTED, DELETE_MENU_SAVE_NVRAM);
    DeleteHelpContext =
        AllocateSpecialBootOption (&BootMenu, L"Help", CON_UNSELECTED, DELETE_MENU_HELP);
    DeleteExitContext =
        AllocateSpecialBootOption (&BootMenu, L"Exit", CON_UNSELECTED, DELETE_MENU_EXIT);

    ST->ConOut->QueryMode (ST->ConOut, ST->ConOut->Mode->Mode, &MaxColumn, &ScreenSize);
    EndRow = ScreenSize - BootMenu.FooterHeight - 1;

    BootMenu.Selection = NULL;
    NVRAMNeedsUpdating = FALSE;
    for (Done = FALSE, ResultContext = NULL; !Done;) {
        PreviousResultContext = ResultContext;
        ResultContext = MenuDisplay (&BootMenu, &Key);
        if (!ResultContext) {
            Done = TRUE;
            break;
        }

        switch (Key.UnicodeChar){
        case CHAR_CARRIAGE_RETURN:
            MenuOption = ResultContext->MenuOption;
            break;
        case 'D':
        case 'd':
            if (ResultContext->MenuOption == BOOT_MENU_SELECTION)
                MenuOption = BOOT_MENU_SELECTION;
            else
                MenuOption = -1;
            break;
        case 'A':
        case 'a':
            MenuOption = DELETE_MENU_ALL;
            break;
        default:
            MenuOption =  -1;
        } // end switch

        if (MenuOption == DELETE_MENU_EXIT) {
            if (NVRAMNeedsUpdating) {
                PrintAt (ResultContext->Menu->Col, ResultContext->Menu->Row + 2, L"NVRAM Not updated. Save NVRAM? [Y to save, N to ignore]");
                WaitForSingleEvent (ST->ConIn->WaitForKey, 0);
                ST->ConIn->ReadKeyStroke (ST->ConIn, &Key);
                if (Key.UnicodeChar == 'Y' || Key.UnicodeChar == 'y') {
                    MenuOption = DELETE_MENU_SAVE_NVRAM;
                }
            }
            Done = TRUE;
        }


        switch (MenuOption) {
        case DELETE_MENU_ALL:
            BootMenu.Selection = NULL;
            DeleteAllBootOptions (&NVRAMNeedsUpdating);
            break;           
        case DELETE_MENU_EXIT:
            break;           
        case DELETE_MENU_HELP:
            PrintMenuHelp(&DeleteHelpMenu,DeleteMenuHelpStr);           
            break;                 
        case DELETE_MENU_SAVE_NVRAM:
            Status = SetNvramForBootMenu (&BootMenu);
            if (EFI_ERROR(Status)) {
                PrintAt (ResultContext->Menu->Col, ResultContext->Menu->Row + 3, L"NVRAM update failed");
            } else {
                NVRAMNeedsUpdating = FALSE;
            }
            break;
        case BOOT_MENU_SELECTION:
            Exit = FALSE;
            while (!Exit) {
                ST->ConOut->SetAttribute (ST->ConOut, BootMenu.ReverseScreenAttribute);
                PrintAt(BootMenu.Col,EndRow,L"Delete selected Boot Option [Y-Yes N-No]: ");
                WaitForSingleEvent (ST->ConIn->WaitForKey, 0);
                ST->ConIn->ReadKeyStroke (ST->ConIn, &Key);
                ST->ConOut->SetAttribute (ST->ConOut, BootMenu.ScreenAttribute);
        
                if (Key.UnicodeChar == 'Y' || Key.UnicodeChar == 'y') {
                    BootMenu.Selection = NULL;
                    if (ResultContext->OptionNumber != NEWADDITION_OPTIONNUMBER)
                        NVRAMNeedsUpdating = TRUE;
                    FreeSpecificBootMenuOption(&BootMenu, ResultContext);
                    Exit = TRUE;
                }
                if (Key.UnicodeChar == 'N' || Key.UnicodeChar == 'n') {
                    Exit = TRUE;
                }
            }
            break;
        default:
            break;
        }
    }

    FreeSpecificBootMenuOption(&BootMenu, DeleteAllContext);
    FreeSpecificBootMenuOption(&BootMenu, SaveNvramContext);
    FreeSpecificBootMenuOption(&BootMenu, DeleteHelpContext);
    FreeSpecificBootMenuOption(&BootMenu, DeleteExitContext);

    ST->ConOut->ClearScreen (ST->ConOut);
    return EFI_SUCCESS;
}

EFI_STATUS
DeleteAllBootOptions (
    OUT BOOLEAN *UpdateNvram)
{
    EFI_INPUT_KEY                   Key;
    SIMPLE_TEXT_OUTPUT_INTERFACE    *ConOut;
    SIMPLE_INPUT_INTERFACE          *ConIn;
    UINTN                           EndRow;
    UINTN                           MaxColumn, ScreenSize;
    BOOLEAN                         Exit,DeleteAll;
    MENU_OPTION                     *MenuOption;
    BOOT_MENU_CONTEXT               *BootContext;
    LIST_ENTRY                      *List;   
    UINTN                           Count;

    ConOut = ST->ConOut;
    ConIn  = ST->ConIn;

    ConOut->QueryMode (ConOut, ConOut->Mode->Mode, &MaxColumn, &ScreenSize);

    //
    // check to see if we have atleast one boot option to delete
    //
    Count = 0;
    List = BootMenu.Head.Flink;
    while (List != &BootMenu.Head) {
        MenuOption = CR(List, MENU_OPTION, Link, MENU_OPTION_SIGNATURE);
        
        // get the next list in line
        List = List->Flink;

        BootContext = (BOOT_MENU_CONTEXT *)MenuOption->Context;
        if( BootContext->MenuOption == BOOT_MENU_SELECTION) {
            Count = 1;
            break;
        }
    } 
    
    //
    // Put prompt for delete
    //
    EndRow = ScreenSize - BootMenu.FooterHeight - 1;
    Exit = FALSE;
    DeleteAll = FALSE;
    *UpdateNvram = FALSE;
    while (!Exit && Count) {
        ConOut->SetAttribute (ConOut, BootMenu.ReverseScreenAttribute);
        PrintAt(BootMenu.Col,EndRow,L"Delete ALL of above Boot Options [Y-Yes N-No]: ");
        WaitForSingleEvent (ConIn->WaitForKey, 0);
        ConIn->ReadKeyStroke (ConIn, &Key);
        ConOut->SetAttribute (ConOut, BootMenu.ScreenAttribute);
        
        if (Key.UnicodeChar == 'Y' || Key.UnicodeChar == 'y') {
            DeleteAll = TRUE;
            Exit = TRUE;
        }
        if (Key.UnicodeChar == 'N' || Key.UnicodeChar == 'n') {
            Exit = TRUE;
        }
    } 

    //
    // Check and Delete the boot options
    //
    if ( DeleteAll) {
        List = BootMenu.Head.Flink;
        while (List != &BootMenu.Head) {
            MenuOption = CR(List, MENU_OPTION, Link, MENU_OPTION_SIGNATURE);
        
            // get the next list in case we end up freeing the current one
            List = List->Flink;

            BootContext = (BOOT_MENU_CONTEXT *)MenuOption->Context;
            if ((BootContext != NULL) && (BootContext->MenuOption == BOOT_MENU_SELECTION)) {
                //
                // Delete the variable from storage
                //
                if (BootContext->OptionNumber != NEWADDITION_OPTIONNUMBER) {
                    *UpdateNvram = TRUE;
                }
                FreeSpecificBootMenuOption(&BootMenu, BootContext);
            }
        } 

        //
        // Clear BootNext and BootOrder as well
        //
    } 

    return EFI_SUCCESS;
}

EFI_STATUS
Bmnt_DisplayBootNextMenu (
    VOID
    ) 
{
    BOOT_MENU_CONTEXT       *ResultContext;
    BOOT_MENU_CONTEXT       *PreviousResultContext;
    BOOT_MENU_CONTEXT       *SaveNvramContext;
    BOOT_MENU_CONTEXT       *ResetBootNext;
    BOOT_MENU_CONTEXT       *BootNextHelpContext;
    BOOT_MENU_CONTEXT       *BootNextExitContext;
    BOOLEAN                 NVRAMNeedsUpdating;
    UINTN                   MenuOption;
    EFI_INPUT_KEY           Key;
    EFI_STATUS              Status;
    BOOLEAN                 Done;
    UINTN                   EndRow;
    UINTN                   MaxColumn, ScreenSize;
    BOOLEAN                 Exit;
    CHAR16                  *Header = L"%EManage BootNext setting.  Select an Operation\n\n";

    // 
    // initialize header text
    //
    FreeBootOrderMenuOfVariables();
    InitializeBootOrderMenuFromVariable();

    BootMenu.Header = Header;
   
    ResetBootNext =
        AllocateSpecialBootOption (&BootMenu, L"Reset BootNext Setting", CON_UNSELECTED, BOOTNEXT_MENU_RESET);
    SaveNvramContext =
        AllocateSpecialBootOption (&BootMenu, L"Save Settings to NVRAM", CON_UNSELECTED, BOOTNEXT_MENU_SAVE_NVRAM);
    BootNextHelpContext =
        AllocateSpecialBootOption (&BootMenu, L"Help", CON_UNSELECTED, BOOTNEXT_MENU_HELP);
    BootNextExitContext =
        AllocateSpecialBootOption (&BootMenu, L"Exit", CON_UNSELECTED, BOOTNEXT_MENU_EXIT);

    ST->ConOut->QueryMode (ST->ConOut, ST->ConOut->Mode->Mode, &MaxColumn, &ScreenSize);
    EndRow = ScreenSize - BootMenu.FooterHeight - 1;

    BootMenu.Selection = NULL;
    NVRAMNeedsUpdating = FALSE;
    for (Done = FALSE, ResultContext = NULL; !Done;) {
        PreviousResultContext = ResultContext;
        ResultContext = MenuDisplay (&BootMenu, &Key);
        if (!ResultContext) {
            Done = TRUE;
            break;
        }

        switch (Key.UnicodeChar){
        case CHAR_CARRIAGE_RETURN:
            MenuOption = ResultContext->MenuOption;
            break;
        case 'B':
        case 'b':
            if (ResultContext->MenuOption == BOOT_MENU_SELECTION)
                MenuOption = BOOT_MENU_SELECTION;
            else
                MenuOption = -1;
            break;
        case 'R':
        case 'r':
            MenuOption = BOOTNEXT_MENU_RESET;
            break;
        default:
            MenuOption =  -1;
        } // end switch

        if (MenuOption == BOOTNEXT_MENU_EXIT) {
            if (NVRAMNeedsUpdating) {
                PrintAt (ResultContext->Menu->Col, ResultContext->Menu->Row + 2, L"NVRAM Not updated. Save NVRAM? [Y to save, N to ignore]");
                WaitForSingleEvent (ST->ConIn->WaitForKey, 0);
                ST->ConIn->ReadKeyStroke (ST->ConIn, &Key);
                if (Key.UnicodeChar == 'Y' || Key.UnicodeChar == 'y') {
                    MenuOption = BOOTNEXT_MENU_SAVE_NVRAM;
                }
            }
            Done = TRUE;
        }

        switch (MenuOption) {
        case BOOTNEXT_MENU_RESET:
            ResetBootNextOption (&NVRAMNeedsUpdating, TRUE);
            break;           
        case BOOTNEXT_MENU_EXIT:
            break;           
        case BOOTNEXT_MENU_HELP:
            PrintMenuHelp(&BootNextHelpMenu,BootNextMenuHelpStr);           
            break;                 
        case BOOTNEXT_MENU_SAVE_NVRAM:
            Status = SetNvramForBootMenu (&BootMenu);
            if (EFI_ERROR(Status)) {
                PrintAt (ResultContext->Menu->Col, ResultContext->Menu->Row + 3, L"NVRAM update failed");
            } else {
                NVRAMNeedsUpdating = FALSE;
            }
            break;
        case BOOT_MENU_SELECTION:
            Exit = FALSE;
            while (!Exit) {
                ST->ConOut->SetAttribute (ST->ConOut, BootMenu.ReverseScreenAttribute);
                PrintAt(BootMenu.Col,EndRow,L"Enter selected Boot Option as 'BootNext' [Y-Yes N-No]: ");
                WaitForSingleEvent (ST->ConIn->WaitForKey, 0);
                ST->ConIn->ReadKeyStroke (ST->ConIn, &Key);
                ST->ConOut->SetAttribute (ST->ConOut, BootMenu.ScreenAttribute);
        
                if (Key.UnicodeChar == 'Y' || Key.UnicodeChar == 'y') {
                    ResetBootNextOption (&NVRAMNeedsUpdating,FALSE);
                    if (ResultContext->OptionNumber != NEWADDITION_OPTIONNUMBER)
                        NVRAMNeedsUpdating = TRUE;
                    ResultContext->IsBootNext = TRUE;
                    Exit = TRUE;
                }
                if (Key.UnicodeChar == 'N' || Key.UnicodeChar == 'n') {
                    Exit = TRUE;
                }
            }
            break;
        default:
            break;
        }
    }

    FreeSpecificBootMenuOption(&BootMenu, ResetBootNext);
    FreeSpecificBootMenuOption(&BootMenu, SaveNvramContext);
    FreeSpecificBootMenuOption(&BootMenu, BootNextHelpContext);
    FreeSpecificBootMenuOption(&BootMenu, BootNextExitContext);

    ST->ConOut->ClearScreen (ST->ConOut);
    return EFI_SUCCESS;
}


EFI_STATUS
ResetBootNextOption (
    OUT BOOLEAN *UpdateNvram,
    IN  BOOLEAN Prompt
    )
{
    EFI_INPUT_KEY                   Key;
    SIMPLE_TEXT_OUTPUT_INTERFACE    *ConOut;
    SIMPLE_INPUT_INTERFACE          *ConIn;
    UINTN                           EndRow, Count;
    UINTN                           MaxColumn, ScreenSize;
    MENU_OPTION                     *MenuOption;
    BOOT_MENU_CONTEXT               *BootContext;
    LIST_ENTRY                      *List;   


    ConOut = ST->ConOut;
    ConIn  = ST->ConIn;

    ConOut->QueryMode (ConOut, ConOut->Mode->Mode, &MaxColumn, &ScreenSize);
     
    Count = 0;

    List = BootMenu.Head.Flink;
    while (List != &BootMenu.Head) {
        MenuOption = CR(List, MENU_OPTION, Link, MENU_OPTION_SIGNATURE);
        
        // get the next list in case we end up freeing the current one
        List = List->Flink;

        BootContext = (BOOT_MENU_CONTEXT *)MenuOption->Context;
        if ((BootContext != NULL) && (BootContext->MenuOption == BOOT_MENU_SELECTION)
                                  && (BootContext->IsBootNext)) {

            if (BootContext->OptionNumber != NEWADDITION_OPTIONNUMBER) {
                *UpdateNvram = TRUE;
            }
            
            Count = 1 ;
            BootContext->IsBootNext = FALSE;
        }
    }

    if(Count && Prompt) {    
        //
        // Print message
        //
        EndRow = ScreenSize - BootMenu.FooterHeight - 1;
        ConOut->SetAttribute (ConOut, BootMenu.ReverseScreenAttribute);
        PrintAt(BootMenu.Col,EndRow,L"'BootNext' variable cleared. Press any key...");
        WaitForSingleEvent (ConIn->WaitForKey, 0);
        ConIn->ReadKeyStroke (ConIn, &Key);
        ConOut->SetAttribute (ConOut, BootMenu.ScreenAttribute);
    }

    return EFI_SUCCESS;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?