boot.c
来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 1,972 行 · 第 1/5 页
C
1,972 行
MenuOption = CR(List, MENU_OPTION, Link, MENU_OPTION_SIGNATURE);
BootContext = (BOOT_MENU_CONTEXT *)MenuOption->Context;
if (BootContext != NULL) {
if (BootContext->FilePathString) {
FreePool (BootContext->FilePathString);
}
if (BootContext->RawOption) {
FreePool (BootContext->RawOption);
}
FreePool (MenuOption->Context);
}
List = List->Flink;
}
MenuFree (Menu);
}
VOID
FreeSpecificBootMenuOption (
IN EFI_MENU *Menu,
IN BOOT_MENU_CONTEXT *Context
)
{
MENU_OPTION *MenuOption;
BOOT_MENU_CONTEXT *BootContext;
LIST_ENTRY *List;
//
// Delete the menu option's Context
//
List = Menu->Head.Flink;
while (List != &Menu->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 == Context)) {
if (BootContext->FilePathString) {
FreePool (BootContext->FilePathString);
}
if (BootContext->Description) {
FreePool (BootContext->Description);
}
if (BootContext->RawOption) {
FreePool (BootContext->RawOption);
}
FreePool (MenuOption->Context);
MenuOption->Context = NULL;
FreePool (MenuOption->Description);
MenuOption->Description = NULL;
RemoveEntryList (&MenuOption->Link);
ASSERT(MenuOption->Signature == MENU_OPTION_SIGNATURE);
FreePool (MenuOption);
}
}
}
EFI_STATUS
FindBootOption (
IN EFI_MENU *Menu,
IN OUT LIST_ENTRY **List,
IN EFI_DEVICE_PATH *DevicePath,
OUT BOOT_MENU_CONTEXT **ReturnBootContext
)
{
MENU_OPTION *MenuOption;
BOOT_MENU_CONTEXT *BootContext;
*ReturnBootContext = NULL;
while (*List != &Menu->Head) {
MenuOption = CR(*List, MENU_OPTION, Link, MENU_OPTION_SIGNATURE);
BootContext = (BOOT_MENU_CONTEXT *)MenuOption->Context;
if (BootContext != NULL) {
if (BootContext->FilePath) {
if (MatchDevicePaths (DevicePath, BootContext->FilePath)) {
*ReturnBootContext = BootContext;
*List = (*List)->Flink;
return EFI_SUCCESS;
}
}
}
*List = (*List)->Flink;
}
return EFI_NOT_FOUND;
}
EFI_STATUS
BootFromFileContext (
IN FILE_MENU_CONTEXT *Context
)
{
EFI_INPUT_KEY Key;
BOOT_MENU_CONTEXT *BootOption;
EFI_STATUS Result;
EFI_STATUS Status;
UINTN ScreenSize, MaxColumn, EndRow;
LIST_ENTRY *List;
ST->ConOut->ClearScreen (ST->ConOut);
ST->ConOut->QueryMode (ST->ConOut, ST->ConOut->Mode->Mode, &MaxColumn, &ScreenSize);
EndRow = ScreenSize - BootMenu.FooterHeight - 1;
PrintEfiFileInfo (Context);
List = BootMenu.Head.Flink;
Result = FindBootOption (&BootMenu, &List, Context->DevicePath, &BootOption);
if (!EFI_ERROR(Result)) {
Print (L" Boot%04x: %s\n\n", BootOption->OptionNumber, BootOption->FilePathString);
}
Status = BootTheOption (Context, BootOption);
if (!EFI_ERROR(Status) || Status == EFI_ALREADY_STARTED) {
return EFI_SUCCESS;
} else {
ST->ConOut->SetAttribute (ST->ConOut, BootMenu.ReverseScreenAttribute);
PrintAt(BootMenu.Col,EndRow,L"Load failed [%r]. Press any key to continue..", Status);
WaitForSingleEvent (ST->ConIn->WaitForKey, 0);
ST->ConIn->ReadKeyStroke (ST->ConIn, &Key);
ST->ConOut->SetAttribute (ST->ConOut, BootMenu.ScreenAttribute);
return Status;
}
}
EFI_STATUS
ConvertFileContextToBootOption (
IN FILE_MENU_CONTEXT *Context
)
{
EFI_INPUT_KEY Key;
SIMPLE_TEXT_OUTPUT_INTERFACE *ConOut;
SIMPLE_INPUT_INTERFACE *ConIn;
EFI_STATUS Result;
UINT8 *RawOption;
CHAR16 *Str;
EFI_DEVICE_PATH *DevicePath;
UINTN Size,ScreenSize, MaxColumn, EndRow;
CHAR16 InputString[MAX_CHAR];
BOOT_MENU_CONTEXT *BootOption;
BOOT_MENU_CONTEXT *NextBootOption;
BOOLEAN Edit, Exit, Next;
CHAR16 LoadOptionStr[MAX_CHAR];
UINTN LoadOptionSize;
UINT8 *LoadOptionPtr;
CHAR16 *LoadOption,*TempLoadOption;
CHAR8 *AsciiChar;
UINTN SizeDevicePath;
LIST_ENTRY *List;
LIST_ENTRY *NextList;
EFI_STATUS NextResult;
ConOut = ST->ConOut;
ConIn = ST->ConIn;
ConOut->ClearScreen (ST->ConOut);
PrintEfiFileInfo (Context);
List = BootMenu.Head.Flink;
Edit = FALSE;
Exit = FALSE;
Next = FALSE;
while (TRUE) {
Result = FindBootOption ( &BootMenu, &List, Context->DevicePath, &BootOption);
if (!EFI_ERROR(Result)) {
Edit = FALSE;
Exit = FALSE;
Next = FALSE;
NextList = List;
NextResult = FindBootOption ( &BootMenu, &NextList, Context->DevicePath, &NextBootOption);
if (!EFI_ERROR(NextResult)) {
Next = TRUE;
}
ConOut->SetAttribute (ConOut, BootMenu.ScreenAttribute);
ConOut->ClearScreen (ST->ConOut);
PrintEfiFileInfo (Context);
Print (L" Boot%04x: %s\n", BootOption->OptionNumber, BootOption->FilePathString);
while (TRUE) {
BmntClearLine();
ConOut->SetAttribute (ConOut, BootMenu.ReverseScreenAttribute);
if (!Next) {
Print(L" Edit this Boot Option or Create a new one? [E-Edit N-New]: ");
} else {
Print(L" Edit/Skip this Boot Option or Create a new one? [E-Edit S-Skip N-New]: ");
}
WaitForSingleEvent (ConIn->WaitForKey, 0);
ConIn->ReadKeyStroke (ConIn, &Key);
if (Key.UnicodeChar == 'E' || Key.UnicodeChar == 'e') {
Edit = TRUE;
Exit = TRUE;
Print(L" Edit");
break;
}
if (Key.UnicodeChar == 'N' || Key.UnicodeChar == 'n') {
Exit = TRUE;
Print(L" New");
break;
}
if ( Next && (Key.UnicodeChar == 'S' || Key.UnicodeChar == 's')) {
Exit = FALSE;
Print(L"Skip");
break;
}
}
if (Exit) {
break;
}
} else {
break;
}
}
//
// Let's make a boot option
//
ConOut->SetAttribute (ConOut, BootMenu.ScreenAttribute);
//
// Update Description Field
//
if (Edit) {
Print (L"\n\n Current Description-->%s", BootOption->Description);
}
Print(L"\n");
do {
BmntClearLine();
ConOut->SetAttribute (ConOut, BootMenu.ReverseScreenAttribute);
Print (L" Enter New Description: ");
ConOut->SetAttribute (ConOut, BootMenu.ScreenAttribute);
Print(L" ");
do {
Input (L"", InputString, sizeof(InputString));
} while (StrLen(InputString) == 0);
} while (InputString[0] == ' ');
//
// Update BootOption Field
//
LoadOption = NULL;
if (Edit) {
if (BootOption->MenuOption == BOOT_MENU_SELECTION) {
if (BootOption->LoadOptionsSize)
LoadOption = BootOption->LoadOptions;
}
//
// Crude check. Currently loadoption can be either
// ascii or Unicode string only..
// hence test 2nd byte to see if it is non-zero
// if non-zero then string is ascii else, unicode
// Bugbug: NEED TO GET A BETTER METHOD (like a header)
// to figure out type of data
if (LoadOption) {
AsciiChar = (UINT8 *)LoadOption;
AsciiChar++;
if(*AsciiChar) {
// ascii string. hence form unicode string
LoadOption = AllocateZeroPool(BootOption->LoadOptionsSize * sizeof(CHAR16));
ASSERT(LoadOption);
TempLoadOption = LoadOption;
AsciiChar = (UINT8 *)BootOption->LoadOptions;
for ( ; *AsciiChar != '\0';AsciiChar++) {
*LoadOption = *AsciiChar;
LoadOption++;
}
*LoadOption = '\0';
Print (L"\n\n Current BootOption-->%-s", TempLoadOption);
FreePool(TempLoadOption);
} else {
// unicode string
Print (L"\n\n Current BootOption-->%-s", LoadOption);
}
}
}
// Get the new load option
LoadOptionSize = 0;
UpdateLoadOption(LoadOptionStr, sizeof(LoadOptionStr), &LoadOptionSize, FALSE);
//
// save the changes
//
ConOut->QueryMode (ConOut, ConOut->Mode->Mode, &MaxColumn, &ScreenSize);
EndRow = ScreenSize - BootMenu.FooterHeight - 1;
Exit = FALSE;
while (!Exit) {
ConOut->SetAttribute (ConOut, BootMenu.ReverseScreenAttribute);
PrintAt(BootMenu.Col,EndRow,L"Save changes to NVRAM [Y-Yes N-No]: ");
WaitForSingleEvent (ConIn->WaitForKey, 0);
ConIn->ReadKeyStroke (ConIn, &Key);
ConOut->SetAttribute (ConOut, BootMenu.ScreenAttribute);
if (Key.UnicodeChar == 'Y' || Key.UnicodeChar == 'y') {
//
// Update BootOption Description
//
if (Edit) {
FreePool (BootOption->Description);
BootOption->Description = NULL;
if(!StrLen(InputString)) {
StrCpy(InputString, L"No Description");
}
BootOption->Description = AllocatePool (StrSize(InputString));
StrCpy (BootOption->Description, InputString);
}
//
// Update BootOption's Load Option
//
if (Edit) {
FreePool (BootOption->LoadOptions);
BootOption->LoadOptions = NULL;
BootOption->LoadOptions = AllocateZeroPool(LoadOptionSize);
CopyMem(BootOption->LoadOptions,LoadOptionStr,LoadOptionSize);
BootOption->LoadOptionsSize = LoadOptionSize;
}
//
// build a new menuoption or update the current one
// allocate memory and copy all the options
//
SizeDevicePath = DevicePathSize (Context->DevicePath);
Size = sizeof(UINT32) + sizeof(UINT16) + StrSize(InputString) + SizeDevicePath + LoadOptionSize;
RawOption = AllocatePool (Size);
*(UINT32 *)RawOption = LOAD_OPTION_ACTIVE;
*(UINT16 *)(RawOption + sizeof(UINT32)) = (UINT16)SizeDevicePath;
Str = (CHAR16 *)(RawOption + sizeof(UINT32) + sizeof(UINT16));
StrCpy (Str, InputString);
DevicePath = (EFI_DEVICE_PATH *)(Str + StrLen(Str) + 1);
CopyMem (DevicePath, Context->DevicePath, DevicePathSize(Context->DevicePath));
LoadOptionPtr = (UINT8 *) ((UINT8 *)(DevicePath) + DevicePathSize(Context->DevicePath));
CopyMem(LoadOptionPtr,LoadOptionStr,LoadOptionSize);
if(Edit) {
FreePool(BootOption->RawOption);
BootOption->RawOption = RawOption;
BootOption->RawOptionSize = Size;
BootOption->LoadOptionModified = TRUE;
} else {
// build the menu option
BootOption = BuildBootMenuContext (RawOption, Size, NEWADDITION_OPTIONNUMBER, L"", FALSE, TRUE);
}
Result = SetNvramForBootMenu (&BootMenu);
if (EFI_ERROR(Result)) {
BmntClearLine();
ConOut->SetAttribute (ConOut, BootMenu.ReverseScreenAttribute);
PrintAt(BootMenu.Col,EndRow,L"NVRAM update failed. Press any key to continue.... ");
WaitForSingleEvent (ConIn->WaitForKey, 0);
ConIn->ReadKeyStroke (ConIn, &Key);
ConOut->SetAttribute (ConOut, BootMenu.ScreenAttribute);
}
Exit = TRUE;
}
if (Key.UnicodeChar == 'N' || Key.UnicodeChar == 'n') {
Exit = TRUE;
}
}
return EFI_SUCCESS;
}
EFI_STATUS
UpdateLoadOption(
IN CHAR16 *LoadOptionStr,
IN UINTN SizeLoadOptionStr,
OUT UINTN *LoadOptionSize,
IN BOOLEAN EditMode)
{
EFI_INPUT_KEY Key;
SIMPLE_TEXT_OUTPUT_INTERFACE *ConOut;
SIMPLE_INPUT_INTERFACE *ConIn;
BOOLEAN Ascii;
CHAR16 *TempStr,*TempStr1;
CHAR8 *AsciiChar;
ConOut = ST->ConOut;
ConIn = ST->ConIn;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?