XTLDR Rewrite #7

Merged
belliash merged 184 commits from xtldr_rewrite into master 2024-01-09 18:51:04 +01:00
2 changed files with 199 additions and 0 deletions
Showing only changes of commit a7c345a9b2 - Show all commits

View File

@ -960,3 +960,192 @@ BlDisplayInputDialog(IN PWCHAR Caption,
BlSetConsoleAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY);
BlClearConsoleScreen();
}
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 = NULL; //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 */
BlSetCursorPosition(4, Handle.PosY + Handle.Height + 4);
BlConsolePrint(L" ", TimeOut);
}
/* Read key stroke */
BlReadKeyStroke(&Key);
if(Key.ScanCode == 0x03 || Key.UnicodeChar == 0x0D)
{
/* ENTER or RightArrow key pressed, boot the highlighted OS */
BlDisplayInfoDialog(L"XTLDR", L"Booting highlighted OS ...");
/* 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 == 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 */
/* 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 */
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 */
BlSetCursorPosition(4, Handle.PosY + Handle.Height + 4);
BlConsolePrint(L"Booting '%S' now... ",
MenuEntries[HighligtedEntryId].EntryName);
/* Disable the timer just in case booting OS fails */
TimeOut = -1;
/* Boot the highlighted (default) OS */
BlDisplayInfoDialog(L"XTLDR", L"Booting highlighted OS ...");
break;
}
}
}
}
}

View File

@ -9,6 +9,10 @@
#include <xtldr.h>
XTCDECL
VOID
BlDisplayBootMenu();
/**
* Initializes a list of operating systems for XTLDR boot menu.
*
@ -186,6 +190,12 @@ BlStartXtLoader(IN EFI_HANDLE ImageHandle,
BlDebugPrint(L"ERROR: Failed to discover and enumerate block devices\n");
}
for(;;)
{
/* Display boot menu */
BlDisplayBootMenu();
}
/* This point should be never reached, if this happen return error code */
return STATUS_EFI_LOAD_ERROR;
}