Add missing description for BlDisplayBootMenu()
All checks were successful
Builds / ExectOS (amd64) (push) Successful in 29s
Builds / ExectOS (i686) (push) Successful in 28s

This commit is contained in:
Rafal Kupiec 2024-01-01 22:08:35 +01:00
parent e1670e5d58
commit afb503961c
Signed by: belliash
GPG Key ID: 4E829243E0CFE6B4

View File

@ -9,6 +9,253 @@
#include <xtldr.h> #include <xtldr.h>
/**
* Displays a simple TUI-based boot menu.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTCDECL
VOID
BlDisplayBootMenu()
{
XTBL_DIALOG_HANDLE Handle;
PXTBL_BOOTMENU_ITEM MenuEntries = NULL;
ULONG Index, NumberOfEntries, HighligtedEntryId;
UINT_PTR EventIndex;
EFI_EVENT Events[2];
EFI_INPUT_KEY Key;
EFI_EVENT TimerEvent;
EFI_STATUS Status;
LONG TimeOut;
PWCHAR TimeOutString;
/* Initialize boot menu list */
BlInitializeBootMenuList(MenuEntries, &NumberOfEntries, &HighligtedEntryId);
/* Get timeout from the configuration */
TimeOutString = BlGetConfigValue(L"TIMEOUT");
TimeOut = -1;
/* Check if timeout is specified */
if(TimeOutString != NULL)
{
/* Convert timeout string to number */
TimeOut = 0;
while(*TimeOutString >= '0' && *TimeOutString <= '9')
{
TimeOut *= 10;
TimeOut += *TimeOutString - '0';
TimeOutString++;
}
}
/* Infinite boot menu loop */
while(TRUE)
{
/* Draw boot menu */
BlpDrawBootMenu(&Handle);
/* Check if there is anything to show in the boot menu */
if(NumberOfEntries > 0) {
/* Iterate through all menu entries */
for(Index = 0; Index < NumberOfEntries; Index++)
{
/* Draw menu entry */
BlpDrawBootMenuEntry(&Handle, MenuEntries[Index].EntryName, Index, Index == HighligtedEntryId);
}
}
else
{
/* No menu entries found, show error message */
BlDisplayErrorDialog(L"XTLDR", L"No boot menu entries found in the configuration. Falling back to shell.");
/* Exit into XTLDR shell */
return;
}
/* Create a timer event for controlling the timeout of the boot menu */
Status = EfiSystemTable->BootServices->CreateEvent(EFI_EVENT_TIMER, EFI_TPL_CALLBACK, NULL, NULL, &TimerEvent);
if(Status == STATUS_EFI_SUCCESS)
{
/* Setup new EFI timer */
Status = EfiSystemTable->BootServices->SetTimer(TimerEvent, TimerPeriodic, 10000000);
}
/* Check is EFI timer was successfully created */
if(Status != STATUS_EFI_SUCCESS)
{
/* Timer creation failed, disable the timer */
TimeOut = -1;
}
/* Initialize EFI events */
Events[0] = EfiSystemTable->ConIn->WaitForKey;
Events[1] = TimerEvent;
/* Infinite boot menu event loop */
while(TRUE)
{
/* Wait for EFI event */
BlWaitForEfiEvent(2, Events, &EventIndex);
/* Check which event was received */
if(EventIndex == 0)
{
/* Key pressed, check if timer is still active */
if(TimeOut != -1)
{
/* Disable the timer */
TimeOut = -1;
/* Cancel timer event */
EfiSystemTable->BootServices->SetTimer(TimerEvent, TimerCancel, 0);
/* Remove the timer message */
BlClearConsoleLine(Handle.PosY + Handle.Height + 4);
}
/* Read key stroke */
BlReadKeyStroke(&Key);
if(Key.ScanCode == 0x03 || Key.UnicodeChar == 0x0D)
{
/* ENTER or RightArrow key pressed, boot the highlighted OS */
BlSetConsoleAttributes(Handle.DialogColor | Handle.TextColor);
BlClearConsoleLine(Handle.PosY + Handle.Height + 4);
BlSetCursorPosition(4, Handle.PosY + Handle.Height + 4);
BlConsolePrint(L"Booting '%S' now...\n", MenuEntries[HighligtedEntryId].EntryName);
/* Boot the highlighted (chosen) OS */
Status = BlInvokeBootProtocol(MenuEntries[HighligtedEntryId].Options);
if(Status != STATUS_SUCCESS)
{
/* Failed to boot OS */
BlDebugPrint(L"ERROR: Failed to boot OS '%S' (Status Code: 0x%lx)\n",
MenuEntries[HighligtedEntryId].EntryName, Status);
BlDisplayErrorDialog(L"XTLDR", L"Failed to startup the selected Operating System.");
}
/* Break from boot menu event loop to redraw whole boot menu */
break;
}
else if(Key.ScanCode == 0x01)
{
/* UpArrow key pressed, go to previous entry if possible */
if(HighligtedEntryId > 0)
{
/* Highlight previous entry */
HighligtedEntryId--;
BlpDrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId + 1].EntryName,
HighligtedEntryId + 1, FALSE);
BlpDrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId].EntryName,
HighligtedEntryId, TRUE);
}
}
else if(Key.ScanCode == 0x02)
{
/* DownArrow key pressed, go to next entry if possible */
if(HighligtedEntryId < NumberOfEntries - 1)
{
/* Highlight next entry */
HighligtedEntryId++;
BlpDrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId - 1].EntryName,
HighligtedEntryId - 1, FALSE);
BlpDrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId].EntryName,
HighligtedEntryId, TRUE);
}
}
else if(Key.ScanCode == 0x09)
{
/* PageUp key pressed, go to top entry */
if(HighligtedEntryId != 0)
{
/* Highlight first entry */
BlpDrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId].EntryName,
HighligtedEntryId, FALSE);
BlpDrawBootMenuEntry(&Handle, MenuEntries[0].EntryName, 0, TRUE);
/* Update highlighted entry ID */
HighligtedEntryId = 0;
}
}
else if(Key.ScanCode == 0x0A)
{
/* PageDown key pressed, go to bottom entry */
if(HighligtedEntryId != NumberOfEntries - 1)
{
/* Highlight last entry */
BlpDrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId].EntryName,
HighligtedEntryId, FALSE);
BlpDrawBootMenuEntry(&Handle, MenuEntries[NumberOfEntries - 1].EntryName,
NumberOfEntries - 1, TRUE);
/* Update highlighted entry ID */
HighligtedEntryId = NumberOfEntries - 1;
}
}
else if(Key.ScanCode == 0x0B)
{
/* F1 key pressed, show help */
BlDisplayInfoDialog(L"XTLDR", L"XTLDR Boot Loader Help");
/* Break from boot menu event loop to redraw whole boot menu */
break;
}
else if(Key.UnicodeChar == 0x65)
{
/* 'e' key pressed, edit the highlighted entry */
BlDisplayErrorDialog(L"XTLDR", L"Editing boot menu entries is not implemented yet!");
/* Break from boot menu event loop to redraw whole boot menu */
break;
}
else if(Key.UnicodeChar == 0x73)
{
/* 's' key pressed, exit into XTLDR shell */
return;
}
}
else
{
/* Timer tick, check if time out expired */
if(TimeOut > 0)
{
/* Update a message and decrease timeout value */
BlSetConsoleAttributes(Handle.DialogColor | Handle.TextColor);
BlClearConsoleLine(Handle.PosY + Handle.Height + 4);
BlSetCursorPosition(4, Handle.PosY + Handle.Height + 4);
BlConsolePrint(L"The highlighted position will be booted automatically in %ld seconds.", TimeOut);
TimeOut--;
}
else if(TimeOut == 0)
{
/* Time out expired, update a message */
BlSetConsoleAttributes(Handle.DialogColor | Handle.TextColor);
BlClearConsoleLine(Handle.PosY + Handle.Height + 4);
BlSetCursorPosition(4, Handle.PosY + Handle.Height + 4);
BlConsolePrint(L"Booting '%S' now...\n", MenuEntries[HighligtedEntryId].EntryName);
/* Disable the timer just in case booting OS fails */
TimeOut = -1;
/* Boot the highlighted (default) OS */
Status = BlInvokeBootProtocol(MenuEntries[HighligtedEntryId].Options);
if(Status != STATUS_SUCCESS)
{
/* Failed to boot OS */
BlDebugPrint(L"ERROR: Failed to boot OS '%S' (Status Code: 0x%lx)\n",
MenuEntries[HighligtedEntryId].EntryName, Status);
BlDisplayErrorDialog(L"XTLDR", L"Failed to startup the selected Operating System.");
}
break;
}
}
}
}
}
/** /**
* Displays a red error dialog box with the specified caption and message. * Displays a red error dialog box with the specified caption and message.
* *
@ -960,251 +1207,3 @@ BlDisplayInputDialog(IN PWCHAR Caption,
BlSetConsoleAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY); BlSetConsoleAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY);
BlClearConsoleScreen(); BlClearConsoleScreen();
} }
XTCDECL
EFI_STATUS
BlInvokeBootProtocol(IN PLIST_ENTRY Options);
XTCDECL
VOID
BlDisplayBootMenu()
{
XTBL_DIALOG_HANDLE Handle;
PXTBL_BOOTMENU_ITEM MenuEntries = NULL;
ULONG Index, NumberOfEntries, HighligtedEntryId;
UINT_PTR EventIndex;
EFI_EVENT Events[2];
EFI_INPUT_KEY Key;
EFI_EVENT TimerEvent;
EFI_STATUS Status;
LONG TimeOut;
PWCHAR TimeOutString;
/* Initialize boot menu list */
BlInitializeBootMenuList(MenuEntries, &NumberOfEntries, &HighligtedEntryId);
/* Get timeout from the configuration */
TimeOutString = BlGetConfigValue(L"TIMEOUT");
TimeOut = -1;
/* Check if timeout is specified */
if(TimeOutString != NULL)
{
/* Convert timeout string to number */
TimeOut = 0;
while(*TimeOutString >= '0' && *TimeOutString <= '9')
{
TimeOut *= 10;
TimeOut += *TimeOutString - '0';
TimeOutString++;
}
}
/* Infinite boot menu loop */
while(TRUE)
{
/* Draw boot menu */
BlpDrawBootMenu(&Handle);
/* Check if there is anything to show in the boot menu */
if(NumberOfEntries > 0) {
/* Iterate through all menu entries */
for(Index = 0; Index < NumberOfEntries; Index++)
{
/* Draw menu entry */
BlpDrawBootMenuEntry(&Handle, MenuEntries[Index].EntryName, Index, Index == HighligtedEntryId);
}
}
else
{
/* No menu entries found, show error message */
BlDisplayErrorDialog(L"XTLDR", L"No boot menu entries found in the configuration. Falling back to shell.");
/* Exit into XTLDR shell */
return;
}
/* Create a timer event for controlling the timeout of the boot menu */
Status = EfiSystemTable->BootServices->CreateEvent(EFI_EVENT_TIMER, EFI_TPL_CALLBACK, NULL, NULL, &TimerEvent);
if(Status == STATUS_EFI_SUCCESS)
{
/* Setup new EFI timer */
Status = EfiSystemTable->BootServices->SetTimer(TimerEvent, TimerPeriodic, 10000000);
}
/* Check is EFI timer was successfully created */
if(Status != STATUS_EFI_SUCCESS)
{
/* Timer creation failed, disable the timer */
TimeOut = -1;
}
/* Initialize EFI events */
Events[0] = EfiSystemTable->ConIn->WaitForKey;
Events[1] = TimerEvent;
/* Infinite boot menu event loop */
while(TRUE)
{
/* Wait for EFI event */
BlWaitForEfiEvent(2, Events, &EventIndex);
/* Check which event was received */
if(EventIndex == 0)
{
/* Key pressed, check if timer is still active */
if(TimeOut != -1)
{
/* Disable the timer */
TimeOut = -1;
/* Cancel timer event */
EfiSystemTable->BootServices->SetTimer(TimerEvent, TimerCancel, 0);
/* Remove the timer message */
BlClearConsoleLine(Handle.PosY + Handle.Height + 4);
}
/* Read key stroke */
BlReadKeyStroke(&Key);
if(Key.ScanCode == 0x03 || Key.UnicodeChar == 0x0D)
{
/* ENTER or RightArrow key pressed, boot the highlighted OS */
BlSetConsoleAttributes(Handle.DialogColor | Handle.TextColor);
BlClearConsoleLine(Handle.PosY + Handle.Height + 4);
BlSetCursorPosition(4, Handle.PosY + Handle.Height + 4);
BlConsolePrint(L"Booting '%S' now...\n", MenuEntries[HighligtedEntryId].EntryName);
/* Boot the highlighted (chosen) OS */
Status = BlInvokeBootProtocol(MenuEntries[HighligtedEntryId].Options);
if(Status != STATUS_SUCCESS)
{
/* Failed to boot OS */
BlDebugPrint(L"ERROR: Failed to boot OS '%S' (Status Code: 0x%lx)\n",
MenuEntries[HighligtedEntryId].EntryName, Status);
BlDisplayErrorDialog(L"XTLDR", L"Failed to startup the selected Operating System.");
}
/* Break from boot menu event loop to redraw whole boot menu */
break;
}
else if(Key.ScanCode == 0x01)
{
/* UpArrow key pressed, go to previous entry if possible */
if(HighligtedEntryId > 0)
{
/* Highlight previous entry */
HighligtedEntryId--;
BlpDrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId + 1].EntryName,
HighligtedEntryId + 1, FALSE);
BlpDrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId].EntryName,
HighligtedEntryId, TRUE);
}
}
else if(Key.ScanCode == 0x02)
{
/* DownArrow key pressed, go to next entry if possible */
if(HighligtedEntryId < NumberOfEntries - 1)
{
/* Highlight next entry */
HighligtedEntryId++;
BlpDrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId - 1].EntryName,
HighligtedEntryId - 1, FALSE);
BlpDrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId].EntryName,
HighligtedEntryId, TRUE);
}
}
else if(Key.ScanCode == 0x09)
{
/* PageUp key pressed, go to top entry */
if(HighligtedEntryId != 0)
{
/* Highlight first entry */
BlpDrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId].EntryName,
HighligtedEntryId, FALSE);
BlpDrawBootMenuEntry(&Handle, MenuEntries[0].EntryName, 0, TRUE);
/* Update highlighted entry ID */
HighligtedEntryId = 0;
}
}
else if(Key.ScanCode == 0x0A)
{
/* PageDown key pressed, go to bottom entry */
if(HighligtedEntryId != NumberOfEntries - 1)
{
/* Highlight last entry */
BlpDrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId].EntryName,
HighligtedEntryId, FALSE);
BlpDrawBootMenuEntry(&Handle, MenuEntries[NumberOfEntries - 1].EntryName,
NumberOfEntries - 1, TRUE);
/* Update highlighted entry ID */
HighligtedEntryId = NumberOfEntries - 1;
}
}
else if(Key.ScanCode == 0x0B)
{
/* F1 key pressed, show help */
BlDisplayInfoDialog(L"XTLDR", L"XTLDR Boot Loader Help");
/* Break from boot menu event loop to redraw whole boot menu */
break;
}
else if(Key.UnicodeChar == 0x65)
{
/* 'e' key pressed, edit the highlighted entry */
BlDisplayErrorDialog(L"XTLDR", L"Editing boot menu entries is not implemented yet!");
/* Break from boot menu event loop to redraw whole boot menu */
break;
}
else if(Key.UnicodeChar == 0x73)
{
/* 's' key pressed, exit into XTLDR shell */
return;
}
}
else
{
/* Timer tick, check if time out expired */
if(TimeOut > 0)
{
/* Update a message and decrease timeout value */
BlSetConsoleAttributes(Handle.DialogColor | Handle.TextColor);
BlClearConsoleLine(Handle.PosY + Handle.Height + 4);
BlSetCursorPosition(4, Handle.PosY + Handle.Height + 4);
BlConsolePrint(L"The highlighted position will be booted automatically in %ld seconds.", TimeOut);
TimeOut--;
}
else if(TimeOut == 0)
{
/* Time out expired, update a message */
BlSetConsoleAttributes(Handle.DialogColor | Handle.TextColor);
BlClearConsoleLine(Handle.PosY + Handle.Height + 4);
BlSetCursorPosition(4, Handle.PosY + Handle.Height + 4);
BlConsolePrint(L"Booting '%S' now...\n", MenuEntries[HighligtedEntryId].EntryName);
/* Disable the timer just in case booting OS fails */
TimeOut = -1;
/* Boot the highlighted (default) OS */
Status = BlInvokeBootProtocol(MenuEntries[HighligtedEntryId].Options);
if(Status != STATUS_SUCCESS)
{
/* Failed to boot OS */
BlDebugPrint(L"ERROR: Failed to boot OS '%S' (Status Code: 0x%lx)\n",
MenuEntries[HighligtedEntryId].EntryName, Status);
BlDisplayErrorDialog(L"XTLDR", L"Failed to startup the selected Operating System.");
}
break;
}
}
}
}
}