boot.c

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

C
1,972
字号
/*++

Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.


Module Name:

    boot.c
    
Abstract:

    Boot Manger type menus



Revision History

--*/

#include "efi.h"
#include "efilib.h"
#include "menu.h"
#include "legacyboot.h"

#define     DIRECTION_UP        1
#define     DIRECTION_DOWN      2

UINT16
AllocateBootOrder ( 
    IN  UINT16  *BootOrderList,
    IN  UINTN   BootOrderSize
    );

BOOLEAN
IsInVarBootOrder (  
    IN  UINT16  BootOption,
    IN  UINT16  *BootOrderList,
    IN  UINTN   BootOrderSize
    );

EFI_STATUS
SetNvramForBootMenu (
    IN  EFI_MENU    *Menu
    );

VOID
BootContextPrint (
     IN struct _MENU_OPTION *MenuOption,
     IN VOID                *Context,
     IN UINTN               *Row,
     IN UINTN               Column
     );

BOOT_MENU_CONTEXT *
AllocateSpecialBootOption (
    IN EFI_MENU     *Menu,
    IN CHAR16       *String,
    IN UINTN        Attribute,
    IN UINTN        Option  
    );

VOID
FreeBootMenu (
    IN EFI_MENU     *Menu
    );

VOID
FreeAllOfBootMenu (
    IN EFI_MENU     *Menu
    );

VOID
FreeSpecificBootMenuOption (
    IN EFI_MENU             *Menu,
    IN BOOT_MENU_CONTEXT    *Context
    );

BOOLEAN
PrintBootHelp(
    IN  CHAR16      *Description
    );

EFI_STATUS
DeleteAllBootOptions (
    OUT BOOLEAN *NVRAMNeedsUpdating
    );


EFI_STATUS
ResetBootNextOption (
    OUT BOOLEAN *NVRAMNeedsUpdating,
    IN  BOOLEAN Prompt
    );

EFI_STATUS
OrderOption(
    IN  BOOT_MENU_CONTEXT   *Context,
    IN  UINTN               Direction,
    OUT BOOLEAN             *UpdateNvram
    );

EFI_STATUS
UpdateLoadOption(
    IN  CHAR16  *LoadOptionStr, 
    IN  UINTN   SizeLoadOptionStr,
    OUT UINTN   *LoadOptionSize,
    IN  BOOLEAN EditMode);

    
EFI_MENU BootMenu = {
    MENU_SIGNATURE, NULL,  
    4, CON_UNSELECTED, CON_ACTIVE_SELECTION, 
    TRUE, 10, 
    NULL,
    NULL, 7, 
    NULL, NULL, NULL, NULL, NULL, FALSE, 0, MENU_ENTRY_FORMAT
};

EFI_MENU BootOrderHelpMenu = {
    MENU_SIGNATURE, NULL,  
    4, CON_UNSELECTED, CON_ACTIVE_SELECTION, 
    TRUE, 10, 
    L"Boot Order Menu Help Screen\n\n", 
    NULL, 7, 
    NULL, NULL, NULL, NULL, NULL, FALSE, 0, MENU_ENTRY_FORMAT
};

EFI_MENU DeleteHelpMenu = {
    MENU_SIGNATURE, NULL,  
    4, CON_UNSELECTED, CON_ACTIVE_SELECTION, 
    TRUE, 10, 
    L"Delete Menu Help Screen\n\n", 
    NULL, 7, 
    NULL, NULL, NULL, NULL, NULL, FALSE, 0, MENU_ENTRY_FORMAT
};

EFI_MENU BootNextHelpMenu = {
    MENU_SIGNATURE, NULL,  
    4, CON_UNSELECTED, CON_ACTIVE_SELECTION, 
    TRUE, 10, 
    L"BootNext Menu Help Screen\n\n", 
    NULL, 7, 
    NULL, NULL, NULL, NULL, NULL, FALSE, 0, MENU_ENTRY_FORMAT
};

UINTN
InitializeBootOrderMenuFromVariable (
    VOID
    )
{
    BOOT_MENU_CONTEXT       *Context;
    UINTN                   Index;
    UINT16                  BootString[10];
    UINT8                   *LoadOptionFromVar, *LoadOption;
    UINTN                   BootOptionSize;
    BOOLEAN                 BootNextFlag;

    UINT16                  *BootOrderList;
    UINTN                   BootOrderListSize;
    UINT16                  *BootNext;
    UINTN                   BootNextSize;


    BootOrderList = LibGetVariableAndSize (VarBootOrder, &EfiGlobalVariable, &BootOrderListSize);
    BootNext = LibGetVariableAndSize (VarBootNext, &EfiGlobalVariable, &BootNextSize);
    if (BootNext) {
        if (BootNextSize != sizeof(UINT16)) {
            FreePool (BootNext);
            BootNext = NULL;
        }
    }

    BootMenu.BottomOfPage = NULL;
    InitializeListHead (&BootMenu.Head);
    for (Index = 0; Index < BootOrderListSize/sizeof(UINT16); Index++) {
        SPrint (BootString, sizeof(BootString), VarBootOption, BootOrderList[Index]);
        LoadOptionFromVar = LibGetVariableAndSize (BootString, &EfiGlobalVariable, &BootOptionSize);
        if (!LoadOptionFromVar) {
            continue;
        }

        LoadOption = AllocateZeroPool(BootOptionSize);
        if (!LoadOption) {
            continue;
        }

        CopyMem(LoadOption,LoadOptionFromVar,BootOptionSize);
        FreePool(LoadOptionFromVar);

        if (BootNext) {
            BootNextFlag = *BootNext == BootOrderList[Index];
        } else {
            BootNextFlag = FALSE;
        }
        Context = BuildBootMenuContext (
                                LoadOption, 
                                BootOptionSize, 
                                BootOrderList[Index], 
                                BootString,
                                BootNextFlag,
                                FALSE
                                );
    }

    if(BootNext) {
        FreePool (BootNext);
    }
    if(BootOrderList) {
        FreePool (BootOrderList);
    }
    return Index;
}

VOID
FreeBootOrderMenuOfVariables (
    VOID
    )
{
    FreeAllOfBootMenu(&BootMenu);
}

    
BOOT_MENU_CONTEXT *
BuildBootMenuContext (
    IN  CHAR8   *BootOption,
    IN  UINTN   BootOptionSize,
    IN  UINT16  BootOptionNumber,
    IN  CHAR16  *BootString,
    IN  BOOLEAN BootNext,
    IN  BOOLEAN Modified
    )
{
    BOOT_MENU_CONTEXT       *Context;
    UINTN                   SizeDevicePath;
    UINT8                   *LoadOption;
    UINT8                   *End;
    UINT32                  FilePathListLength;
    UINTN                   StringSize;
    
    LoadOption = BootOption;

    Context = AllocateZeroPool (sizeof(BOOT_MENU_CONTEXT));
    if (!Context) {
        return NULL;
    }

    Context->OptionNumber = BootOptionNumber;
    Context->IsBootNext = BootNext;
    Context->LoadOptionModified = Modified;

    End = LoadOption + BootOptionSize;
    Context->RawOption = BootOption;
    Context->RawOptionSize = BootOptionSize;
    Context->Attributes = *(UINT32 *) LoadOption;
    Context->IsActive = (BOOLEAN)(Context->Attributes & LOAD_OPTION_ACTIVE);
    LoadOption += sizeof(UINT32);
    
    FilePathListLength = *(UINT16 *) LoadOption;
    LoadOption += sizeof(UINT16);

    StringSize = StrSize((CHAR16 *)LoadOption);
    Context->Description = AllocateZeroPool (StringSize);
    CopyMem (Context->Description, (CHAR16 *)LoadOption, StringSize);
    
    LoadOption += StringSize;

    SizeDevicePath = DevicePathSize ((EFI_DEVICE_PATH *)LoadOption);
    if (SizeDevicePath > FilePathListLength) {
        SizeDevicePath = FilePathListLength;
    }
    if ((LoadOption + SizeDevicePath) > End) {
        Context->IsActive = FALSE;
        SizeDevicePath = End - LoadOption;
    }

    //
    // To avoid alignment problems copy to an aligned buffer
    //
    Context->FilePath = AllocatePool (SizeDevicePath);
    CopyMem (Context->FilePath, (EFI_DEVICE_PATH *)LoadOption, SizeDevicePath);
    Context->FilePathString = DevicePathToStr (Context->FilePath);
    LoadOption += SizeDevicePath;

    Context->LoadOptionsSize = BootOptionSize - sizeof(UINT32) - sizeof(UINT16) - StringSize - SizeDevicePath;
    Context->LoadOptions = AllocatePool(Context->LoadOptionsSize);
    CopyMem (Context->LoadOptions, LoadOption, Context->LoadOptionsSize);

    StrCpy (Context->BootString, BootString);

    Context->MenuOption = BOOT_MENU_SELECTION;
    Context->Menu = AllocateMenuOption (&BootMenu, Context->Description, CON_UNSELECTED, Context);
    Context->Menu->ContextPrint = BootContextPrint;
    
    return Context;
}


EFI_STATUS
Bmnt_DisplayBootOrderMenu (
    VOID
    ) 
{
    BOOT_MENU_CONTEXT       *ResultContext;
    BOOT_MENU_CONTEXT       *PreviousResultContext;
    BOOT_MENU_CONTEXT       *SaveNvramContext;
    BOOT_MENU_CONTEXT       *BootHelpContext;
    BOOT_MENU_CONTEXT       *BootExitContext;
    BOOLEAN                 NVRAMNeedsUpdating;
    UINTN                   MenuOption;
    EFI_INPUT_KEY           Key;
    EFI_STATUS              Status;
    BOOLEAN                 Done;
    UINTN                   Direction;
    CHAR16                  *Header = L"%EChange boot order.  Select an Operation\n\n";

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

    BootMenu.Header = Header;

    SaveNvramContext = 
        AllocateSpecialBootOption (&BootMenu, L"Save Settings to NVRAM", CON_UNSELECTED, BOOT_MENU_SAVE_NVRAM);
    BootHelpContext =
        AllocateSpecialBootOption (&BootMenu, L"Help", CON_UNSELECTED, BOOT_MENU_HELP);
    BootExitContext =
        AllocateSpecialBootOption (&BootMenu, L"Exit", CON_UNSELECTED, BOOT_MENU_EXIT);

    BootMenu.Selection = NULL;
    NVRAMNeedsUpdating = FALSE;
    for (Done = FALSE, ResultContext = NULL; !Done;) {
        PreviousResultContext = ResultContext;
        ResultContext = MenuDisplay (&BootMenu, &Key);
        if (!ResultContext) {
            Done = TRUE;
            break;
        }
        
        //
        // default move option down
        //
        Direction = DIRECTION_DOWN; 

        switch (Key.UnicodeChar){
        case CHAR_CARRIAGE_RETURN:
            if (ResultContext->MenuOption != BOOT_MENU_SELECTION) {
                MenuOption = ResultContext->MenuOption;
            } else {
                MenuOption = -1;
            }
            break;
        case 'U':
        case 'u':
            Direction = DIRECTION_UP;
        case 'D':
        case 'd':
            if (ResultContext->MenuOption == BOOT_MENU_SELECTION) {
                MenuOption = BOOT_MENU_SELECTION;
            } else {
                MenuOption = -1;
            }
            break;
        default:
            MenuOption =  -1;
        } // end switch

        if (MenuOption == BOOT_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 = BOOT_MENU_SAVE_NVRAM;
                }
            }
            Done = TRUE;
        }

        switch (MenuOption) {
        case BOOT_MENU_EXIT:
            break;           
        case BOOT_MENU_HELP:
            PrintMenuHelp(&BootOrderHelpMenu,BootOrderMenuHelpStr);           
            break;                 
        case BOOT_MENU_SAVE_NVRAM:
            Status = SetNvramForBootMenu (&BootMenu);

⌨️ 快捷键说明

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