Implement boot entry editor
This commit is contained in:
parent
b68514b176
commit
c6643125e1
229
xtldr/config.c
229
xtldr/config.c
@ -4,11 +4,84 @@
|
|||||||
* FILE: xtldr/config.c
|
* FILE: xtldr/config.c
|
||||||
* DESCRIPTION: XT Boot Loader Configuration
|
* DESCRIPTION: XT Boot Loader Configuration
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||||
|
* Aiken Harris <harraiken91@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <xtldr.h>
|
#include <xtldr.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieves the value of a specific OS boot option from a list.
|
||||||
|
*
|
||||||
|
* @param Options
|
||||||
|
* A pointer to the head of a list of XTBL_CONFIG_ENTRY structures.
|
||||||
|
*
|
||||||
|
* @param OptionName
|
||||||
|
* A pointer to wide string that contains the name of the boot option to retrieve.
|
||||||
|
*
|
||||||
|
* @param OptionValue
|
||||||
|
* A pointer to a variable that receives a pointer to the retrieved boot option's value.
|
||||||
|
*
|
||||||
|
* @return This routine returns a status code.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTCDECL
|
||||||
|
EFI_STATUS
|
||||||
|
BlGetBootOptionValue(IN PLIST_ENTRY Options,
|
||||||
|
IN CONST PWCHAR OptionName,
|
||||||
|
OUT PWCHAR *OptionValue)
|
||||||
|
{
|
||||||
|
PXTBL_CONFIG_ENTRY ConfigEntry;
|
||||||
|
PLIST_ENTRY ConfigList;
|
||||||
|
ULONG KeyLength, ValueLength;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
/* Assume the option will not be found */
|
||||||
|
*OptionValue = NULL;
|
||||||
|
|
||||||
|
/* Get the length of the option name we are looking for */
|
||||||
|
KeyLength = RtlWideStringLength(OptionName, 0);
|
||||||
|
|
||||||
|
/* Start iterating from the first entry in the options list */
|
||||||
|
ConfigList = Options->Flink;
|
||||||
|
while(ConfigList != Options)
|
||||||
|
{
|
||||||
|
/* Get the container record for the current config entry */
|
||||||
|
ConfigEntry = CONTAIN_RECORD(ConfigList, XTBL_CONFIG_ENTRY, Flink);
|
||||||
|
|
||||||
|
/* Compare the current entry's name with the requested option name */
|
||||||
|
if(RtlCompareWideStringInsensitive(ConfigEntry->Name, OptionName, KeyLength) == 0)
|
||||||
|
{
|
||||||
|
/* Found the option, now prepare to copy its value */
|
||||||
|
ValueLength = RtlWideStringLength(ConfigEntry->Value, 0);
|
||||||
|
|
||||||
|
/* Allocate memory for the output value string */
|
||||||
|
Status = BlAllocateMemoryPool((ValueLength + 1) * sizeof(WCHAR), (PVOID *)OptionValue);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Memory allocation failure, print debug message and return status code */
|
||||||
|
BlDebugPrint(L"ERROR: Memory allocation failure (Status Code: 0x%zX)\n", Status);
|
||||||
|
*OptionValue = NULL;
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the value and NULL-terminate the new string */
|
||||||
|
RtlCopyMemory(*OptionValue, ConfigEntry->Value, ValueLength * sizeof(WCHAR));
|
||||||
|
(*OptionValue)[ValueLength] = L'\0';
|
||||||
|
|
||||||
|
/* Successfully retrieved the option value, return success */
|
||||||
|
return STATUS_EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move to the next entry in the list */
|
||||||
|
ConfigList = ConfigList->Flink;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Option not found */
|
||||||
|
return STATUS_EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a boolean value of the specified configuration key.
|
* Returns a boolean value of the specified configuration key.
|
||||||
*
|
*
|
||||||
@ -101,6 +174,156 @@ BlGetConfigValue(IN CONST PWCHAR ConfigName)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the list of user-editable boot options.
|
||||||
|
*
|
||||||
|
* @param OptionsArray
|
||||||
|
* A pointer to a variable that will receive the pointer to the array of editable option names.
|
||||||
|
*
|
||||||
|
* @param OptionsCount
|
||||||
|
* A pointer to a variable that will be updated with the number of elements in the OptionsArray.
|
||||||
|
*
|
||||||
|
* @return This routine does not return any value.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTCDECL
|
||||||
|
VOID
|
||||||
|
BlGetEditableOptions(OUT CONST PWCHAR **OptionsArray,
|
||||||
|
OUT PSIZE_T OptionsCount)
|
||||||
|
{
|
||||||
|
ULONG Count = 0;
|
||||||
|
|
||||||
|
/* Return a pointer to the global array of editable options */
|
||||||
|
*OptionsArray = BlpEditableConfigOptions;
|
||||||
|
|
||||||
|
/* Calculate the number of elements in the array */
|
||||||
|
while(BlpEditableConfigOptions[Count])
|
||||||
|
{
|
||||||
|
Count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the number of elements */
|
||||||
|
*OptionsCount = Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value of a specific OS boot option in a list, or adds it if it doesn't exist.
|
||||||
|
*
|
||||||
|
* @param Options
|
||||||
|
* A pointer to the head of a list of XTBL_CONFIG_ENTRY structures.
|
||||||
|
*
|
||||||
|
* @param OptionName
|
||||||
|
* A pointer to a wide string that contains the name of the boot option to set.
|
||||||
|
*
|
||||||
|
* @param OptionValue
|
||||||
|
* A pointer to a wide string that contains the new value for the boot option.
|
||||||
|
*
|
||||||
|
* @return This routine returns a status code.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTCDECL
|
||||||
|
EFI_STATUS
|
||||||
|
BlSetBootOptionValue(IN PLIST_ENTRY Options,
|
||||||
|
IN CONST PWCHAR OptionName,
|
||||||
|
IN CONST PWCHAR OptionValue)
|
||||||
|
{
|
||||||
|
PXTBL_CONFIG_ENTRY ConfigEntry;
|
||||||
|
PLIST_ENTRY ConfigList;
|
||||||
|
ULONG Length;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
/* Get the length of the option name we are looking for */
|
||||||
|
Length = RtlWideStringLength(OptionName, 0);
|
||||||
|
|
||||||
|
/* Start iterating from the first entry in the options list */
|
||||||
|
ConfigList = Options->Flink;
|
||||||
|
while(ConfigList != Options)
|
||||||
|
{
|
||||||
|
/* Get the container record for the current config entry */
|
||||||
|
ConfigEntry = CONTAIN_RECORD(ConfigList, XTBL_CONFIG_ENTRY, Flink);
|
||||||
|
|
||||||
|
/* Compare the current entry's name with the requested option name */
|
||||||
|
if(RtlCompareWideStringInsensitive(ConfigEntry->Name, OptionName, Length) == 0)
|
||||||
|
{
|
||||||
|
/* Found the option, get its length */
|
||||||
|
Length = RtlWideStringLength(OptionValue, 0);
|
||||||
|
|
||||||
|
/* Reallocate memory for the new value */
|
||||||
|
Status = BlFreeMemoryPool(ConfigEntry->Value);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Failed to free memory, return status code */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate new memory for the updated value */
|
||||||
|
Status = BlAllocateMemoryPool((Length + 1) * sizeof(WCHAR), (PVOID *)&ConfigEntry->Value);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Memory allocation failure, print debug message and return status code */
|
||||||
|
BlDebugPrint(L"ERROR: Memory allocation failure (Status Code: 0x%zX)\\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the value and NULL-terminate the new string */
|
||||||
|
RtlCopyMemory(ConfigEntry->Value, OptionValue, Length * sizeof(WCHAR));
|
||||||
|
ConfigEntry->Value[Length] = L'\0';
|
||||||
|
return STATUS_EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move to the next entry in the list */
|
||||||
|
ConfigList = ConfigList->Flink;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Option not found, allocate memory for the new one */
|
||||||
|
Status = BlAllocateMemoryPool(sizeof(XTBL_CONFIG_ENTRY), (PVOID *)&ConfigEntry);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Memory allocation failure, print debug message and return status code */
|
||||||
|
BlDebugPrint(L"ERROR: Memory allocation failure (Status Code: 0x%zX)\\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate memory for the option name */
|
||||||
|
Length = RtlWideStringLength(OptionName, 0);
|
||||||
|
Status = BlAllocateMemoryPool((Length + 1) * sizeof(WCHAR), (PVOID *)&ConfigEntry->Name);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Memory allocation failure, print debug message and return status code */
|
||||||
|
BlDebugPrint(L"ERROR: Memory allocation failure (Status Code: 0x%zX)\\n", Status);
|
||||||
|
BlFreeMemoryPool(ConfigEntry);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the option name and NULL-terminate the new string */
|
||||||
|
RtlCopyMemory(ConfigEntry->Name, OptionName, Length * sizeof(WCHAR));
|
||||||
|
ConfigEntry->Name[Length] = L'\0';
|
||||||
|
|
||||||
|
/* Allocate memory for the option value */
|
||||||
|
Length = RtlWideStringLength(OptionValue, 0);
|
||||||
|
Status = BlAllocateMemoryPool((Length + 1) * sizeof(WCHAR), (PVOID *)&ConfigEntry->Value);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Memory allocation failure, print debug message and return status code */
|
||||||
|
BlDebugPrint(L"ERROR: Memory allocation failure (Status Code: 0x%zX)\\n", Status);
|
||||||
|
BlFreeMemoryPool(ConfigEntry->Name);
|
||||||
|
BlFreeMemoryPool(ConfigEntry);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the value and NULL-terminate the new string */
|
||||||
|
RtlCopyMemory(ConfigEntry->Value, OptionValue, Length * sizeof(WCHAR));
|
||||||
|
ConfigEntry->Value[Length] = L'\0';
|
||||||
|
|
||||||
|
/* Insert the new config entry at the end of the options list */
|
||||||
|
RtlInsertTailList(Options, &ConfigEntry->Flink);
|
||||||
|
|
||||||
|
/* Return success */
|
||||||
|
return STATUS_EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates existing configuration value.
|
* Updates existing configuration value.
|
||||||
*
|
*
|
||||||
@ -110,7 +333,7 @@ BlGetConfigValue(IN CONST PWCHAR ConfigName)
|
|||||||
* @param ConfigValue
|
* @param ConfigValue
|
||||||
* Specifies the new configuration value.
|
* Specifies the new configuration value.
|
||||||
*
|
*
|
||||||
* @return This routine returns status code.
|
* @return This routine returns a status code.
|
||||||
*
|
*
|
||||||
* @since XT 1.0
|
* @since XT 1.0
|
||||||
*/
|
*/
|
||||||
@ -174,7 +397,7 @@ BlSetConfigValue(IN CONST PWCHAR ConfigName,
|
|||||||
/**
|
/**
|
||||||
* Loads and parses XTLDR configuration file.
|
* Loads and parses XTLDR configuration file.
|
||||||
*
|
*
|
||||||
* @return This routine returns status code.
|
* @return This routine returns a status code.
|
||||||
*
|
*
|
||||||
* @since XT 1.0
|
* @since XT 1.0
|
||||||
*/
|
*/
|
||||||
@ -568,7 +791,7 @@ BlpParseConfigFile(IN CONST PCHAR RawConfig,
|
|||||||
* @param ConfigData
|
* @param ConfigData
|
||||||
* Provides a buffer to store the data read from the configuration file.
|
* Provides a buffer to store the data read from the configuration file.
|
||||||
*
|
*
|
||||||
* @return This routine returns status code.
|
* @return This routine returns a status code.
|
||||||
*
|
*
|
||||||
* @since XT 1.0
|
* @since XT 1.0
|
||||||
*/
|
*/
|
||||||
|
@ -21,6 +21,13 @@ LIST_ENTRY BlpConfig;
|
|||||||
/* XT Boot Loader loaded configuration */
|
/* XT Boot Loader loaded configuration */
|
||||||
LIST_ENTRY BlpConfigSections;
|
LIST_ENTRY BlpConfigSections;
|
||||||
|
|
||||||
|
/* List of user-editable boot options */
|
||||||
|
PWCHAR BlpEditableConfigOptions[] = {
|
||||||
|
L"BootModules", L"SystemType", L"SystemPath",
|
||||||
|
L"KernelFile", L"InitrdFile", L"HalFile",
|
||||||
|
L"Parameters", NULL
|
||||||
|
};
|
||||||
|
|
||||||
/* XT Boot Loader protocol */
|
/* XT Boot Loader protocol */
|
||||||
XTBL_LOADER_PROTOCOL BlpLdrProtocol;
|
XTBL_LOADER_PROTOCOL BlpLdrProtocol;
|
||||||
|
|
||||||
@ -41,3 +48,4 @@ EFI_HANDLE EfiImageHandle;
|
|||||||
|
|
||||||
/* EFI System Table */
|
/* EFI System Table */
|
||||||
PEFI_SYSTEM_TABLE EfiSystemTable;
|
PEFI_SYSTEM_TABLE EfiSystemTable;
|
||||||
|
|
||||||
|
@ -24,6 +24,9 @@ EXTERN LIST_ENTRY BlpConfig;
|
|||||||
/* XT Boot Loader loaded configuration */
|
/* XT Boot Loader loaded configuration */
|
||||||
EXTERN LIST_ENTRY BlpConfigSections;
|
EXTERN LIST_ENTRY BlpConfigSections;
|
||||||
|
|
||||||
|
/* List of user-editable boot options */
|
||||||
|
EXTERN PWCHAR BlpEditableConfigOptions[];
|
||||||
|
|
||||||
/* XT Boot Loader protocol */
|
/* XT Boot Loader protocol */
|
||||||
EXTERN XTBL_LOADER_PROTOCOL BlpLdrProtocol;
|
EXTERN XTBL_LOADER_PROTOCOL BlpLdrProtocol;
|
||||||
|
|
||||||
|
@ -71,6 +71,10 @@ XTCDECL
|
|||||||
VOID
|
VOID
|
||||||
BlDisplayBootMenu();
|
BlDisplayBootMenu();
|
||||||
|
|
||||||
|
XTCDECL
|
||||||
|
VOID
|
||||||
|
BlDisplayEditMenu(IN PXTBL_BOOTMENU_ITEM MenuEntry);
|
||||||
|
|
||||||
XTCDECL
|
XTCDECL
|
||||||
VOID
|
VOID
|
||||||
BlDisplayErrorDialog(IN PWCHAR Caption,
|
BlDisplayErrorDialog(IN PWCHAR Caption,
|
||||||
@ -134,6 +138,12 @@ BOOLEAN
|
|||||||
BlGetBooleanParameter(IN CONST PWCHAR Parameters,
|
BlGetBooleanParameter(IN CONST PWCHAR Parameters,
|
||||||
IN CONST PWCHAR Needle);
|
IN CONST PWCHAR Needle);
|
||||||
|
|
||||||
|
XTCDECL
|
||||||
|
EFI_STATUS
|
||||||
|
BlGetBootOptionValue(IN PLIST_ENTRY Options,
|
||||||
|
IN CONST PWCHAR OptionName,
|
||||||
|
OUT PWCHAR *OptionValue);
|
||||||
|
|
||||||
XTCDECL
|
XTCDECL
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
BlGetConfigBooleanValue(IN CONST PWCHAR ConfigName);
|
BlGetConfigBooleanValue(IN CONST PWCHAR ConfigName);
|
||||||
@ -147,6 +157,11 @@ EFI_STATUS
|
|||||||
BlGetConfigurationTable(IN PEFI_GUID TableGuid,
|
BlGetConfigurationTable(IN PEFI_GUID TableGuid,
|
||||||
OUT PVOID *Table);
|
OUT PVOID *Table);
|
||||||
|
|
||||||
|
XTCDECL
|
||||||
|
VOID
|
||||||
|
BlGetEditableOptions(OUT CONST PWCHAR **OptionsArray,
|
||||||
|
OUT PSIZE_T OptionsCount);
|
||||||
|
|
||||||
XTCDECL
|
XTCDECL
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BlGetEfiPath(IN PWCHAR SystemPath,
|
BlGetEfiPath(IN PWCHAR SystemPath,
|
||||||
@ -332,6 +347,12 @@ XTCDECL
|
|||||||
VOID
|
VOID
|
||||||
BlResetConsoleInputBuffer();
|
BlResetConsoleInputBuffer();
|
||||||
|
|
||||||
|
XTCDECL
|
||||||
|
EFI_STATUS
|
||||||
|
BlSetBootOptionValue(IN PLIST_ENTRY Options,
|
||||||
|
IN CONST PWCHAR OptionName,
|
||||||
|
IN CONST PWCHAR OptionValue);
|
||||||
|
|
||||||
XTCDECL
|
XTCDECL
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BlSetConfigValue(IN CONST PWCHAR ConfigName,
|
BlSetConfigValue(IN CONST PWCHAR ConfigName,
|
||||||
@ -456,6 +477,18 @@ VOID
|
|||||||
BlpDrawDialogProgressBar(IN PXTBL_DIALOG_HANDLE Handle,
|
BlpDrawDialogProgressBar(IN PXTBL_DIALOG_HANDLE Handle,
|
||||||
IN UCHAR Percentage);
|
IN UCHAR Percentage);
|
||||||
|
|
||||||
|
XTCDECL
|
||||||
|
VOID
|
||||||
|
BlpDrawEditMenu(OUT PXTBL_DIALOG_HANDLE Handle);
|
||||||
|
|
||||||
|
XTCDECL
|
||||||
|
EFI_STATUS
|
||||||
|
BlpDrawEditMenuEntry(IN PXTBL_DIALOG_HANDLE Handle,
|
||||||
|
IN PWCHAR OptionName,
|
||||||
|
IN PWCHAR OptionValue,
|
||||||
|
IN UINT Position,
|
||||||
|
IN BOOLEAN Highlighted);
|
||||||
|
|
||||||
XTCDECL
|
XTCDECL
|
||||||
PEFI_DEVICE_PATH_PROTOCOL
|
PEFI_DEVICE_PATH_PROTOCOL
|
||||||
BlpDuplicateDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath);
|
BlpDuplicateDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath);
|
||||||
|
456
xtldr/textui.c
456
xtldr/textui.c
@ -107,6 +107,8 @@ BlDisplayBootMenu()
|
|||||||
BlpDrawBootMenuEntry(&Handle, MenuEntries[TopVisibleEntry + Index].EntryName,
|
BlpDrawBootMenuEntry(&Handle, MenuEntries[TopVisibleEntry + Index].EntryName,
|
||||||
Index, (TopVisibleEntry + Index) == HighligtedEntryId);
|
Index, (TopVisibleEntry + Index) == HighligtedEntryId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Clear redraw entries flag */
|
||||||
RedrawEntries = FALSE;
|
RedrawEntries = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -198,6 +200,7 @@ BlDisplayBootMenu()
|
|||||||
if(HighligtedEntryId > 0)
|
if(HighligtedEntryId > 0)
|
||||||
{
|
{
|
||||||
/* Highlight previous entry */
|
/* Highlight previous entry */
|
||||||
|
OldHighligtedEntryId = HighligtedEntryId;
|
||||||
HighligtedEntryId--;
|
HighligtedEntryId--;
|
||||||
|
|
||||||
/* Check if we need to scroll the view */
|
/* Check if we need to scroll the view */
|
||||||
@ -214,9 +217,6 @@ BlDisplayBootMenu()
|
|||||||
OldHighligtedEntryId - TopVisibleEntry, FALSE);
|
OldHighligtedEntryId - TopVisibleEntry, FALSE);
|
||||||
BlpDrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId].EntryName,
|
BlpDrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId].EntryName,
|
||||||
HighligtedEntryId - TopVisibleEntry, TRUE);
|
HighligtedEntryId - TopVisibleEntry, TRUE);
|
||||||
|
|
||||||
/* Update old highlighted entry */
|
|
||||||
OldHighligtedEntryId = HighligtedEntryId;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(Key.ScanCode == 0x02)
|
else if(Key.ScanCode == 0x02)
|
||||||
@ -225,6 +225,7 @@ BlDisplayBootMenu()
|
|||||||
if(HighligtedEntryId < NumberOfEntries - 1)
|
if(HighligtedEntryId < NumberOfEntries - 1)
|
||||||
{
|
{
|
||||||
/* Highlight next entry */
|
/* Highlight next entry */
|
||||||
|
OldHighligtedEntryId = HighligtedEntryId;
|
||||||
HighligtedEntryId++;
|
HighligtedEntryId++;
|
||||||
|
|
||||||
/* Check if we need to scroll the view */
|
/* Check if we need to scroll the view */
|
||||||
@ -241,9 +242,6 @@ BlDisplayBootMenu()
|
|||||||
OldHighligtedEntryId - TopVisibleEntry, FALSE);
|
OldHighligtedEntryId - TopVisibleEntry, FALSE);
|
||||||
BlpDrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId].EntryName,
|
BlpDrawBootMenuEntry(&Handle, MenuEntries[HighligtedEntryId].EntryName,
|
||||||
HighligtedEntryId - TopVisibleEntry, TRUE);
|
HighligtedEntryId - TopVisibleEntry, TRUE);
|
||||||
|
|
||||||
/* Update old highlighted entry */
|
|
||||||
OldHighligtedEntryId = HighligtedEntryId;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(Key.ScanCode == 0x09)
|
else if(Key.ScanCode == 0x09)
|
||||||
@ -326,7 +324,7 @@ BlDisplayBootMenu()
|
|||||||
else if(Key.UnicodeChar == 0x65)
|
else if(Key.UnicodeChar == 0x65)
|
||||||
{
|
{
|
||||||
/* 'e' key pressed, edit the highlighted entry */
|
/* 'e' key pressed, edit the highlighted entry */
|
||||||
BlDisplayErrorDialog(L"XTLDR", L"Editing boot menu entries is not implemented yet!");
|
BlDisplayEditMenu(&MenuEntries[HighligtedEntryId]);
|
||||||
RedrawBootMenu = TRUE;
|
RedrawBootMenu = TRUE;
|
||||||
|
|
||||||
/* Break from boot menu event loop to redraw whole boot menu */
|
/* Break from boot menu event loop to redraw whole boot menu */
|
||||||
@ -379,6 +377,232 @@ BlDisplayBootMenu()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays a simple TUI-based edit menu.
|
||||||
|
*
|
||||||
|
* @return This routine does not return any value.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTCDECL
|
||||||
|
VOID
|
||||||
|
BlDisplayEditMenu(IN PXTBL_BOOTMENU_ITEM MenuEntry)
|
||||||
|
{
|
||||||
|
ULONG HighligtedOptionId, Index, NumberOfOptions, OldHighligtedOptionId, TopVisibleEntry, VisibleEntries;
|
||||||
|
XTBL_DIALOG_HANDLE Handle;
|
||||||
|
BOOLEAN RedrawEditMenu, RedrawEntries;
|
||||||
|
EFI_INPUT_KEY Key;
|
||||||
|
UINT_PTR EventIndex;
|
||||||
|
PWCHAR NewValue, OptionName, OriginalValue, Value, ValueToEdit;
|
||||||
|
CONST PWCHAR *EditableOptions;
|
||||||
|
|
||||||
|
/* Draw edit menu */
|
||||||
|
BlpDrawEditMenu(&Handle);
|
||||||
|
|
||||||
|
/* Get the list of user editable options */
|
||||||
|
BlGetEditableOptions(&EditableOptions, &NumberOfOptions);
|
||||||
|
|
||||||
|
/* Calculate how many entries can be visible in the menu box */
|
||||||
|
VisibleEntries = Handle.Height - 2;
|
||||||
|
|
||||||
|
/* Assume the first option is highlighted by default */
|
||||||
|
HighligtedOptionId = 0;
|
||||||
|
OldHighligtedOptionId = 0;
|
||||||
|
TopVisibleEntry = 0;
|
||||||
|
|
||||||
|
/* Set redraw flags to not redraw the menu itself, but fill it with entries */
|
||||||
|
RedrawEditMenu = FALSE;
|
||||||
|
RedrawEntries = TRUE;
|
||||||
|
|
||||||
|
/* Infinite edit menu loop */
|
||||||
|
while(TRUE)
|
||||||
|
{
|
||||||
|
/* Redraw edit menu frame if requested */
|
||||||
|
if(RedrawEditMenu)
|
||||||
|
{
|
||||||
|
BlpDrawEditMenu(&Handle);
|
||||||
|
RedrawEditMenu = FALSE;
|
||||||
|
RedrawEntries = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sanity check to ensure we do not display more entries than possible */
|
||||||
|
if(VisibleEntries > NumberOfOptions)
|
||||||
|
{
|
||||||
|
VisibleEntries = NumberOfOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if we need to redraw boot menu entries */
|
||||||
|
if(RedrawEntries)
|
||||||
|
{
|
||||||
|
/* Iterate through all menu entries */
|
||||||
|
for(Index = 0; Index < VisibleEntries; Index++)
|
||||||
|
{
|
||||||
|
/* Draw menu entry */
|
||||||
|
BlGetBootOptionValue(MenuEntry->Options, EditableOptions[TopVisibleEntry + Index], &Value);
|
||||||
|
BlpDrawEditMenuEntry(&Handle, EditableOptions[TopVisibleEntry + Index], Value, Index,
|
||||||
|
(TopVisibleEntry + Index) == HighligtedOptionId);
|
||||||
|
|
||||||
|
/* Free allocated value string if needed */
|
||||||
|
if(Value != NULL)
|
||||||
|
{
|
||||||
|
BlFreeMemoryPool(Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear redraw entries flag */
|
||||||
|
RedrawEntries = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for EFI event and read key stroke */
|
||||||
|
BlWaitForEfiEvent(1, &EfiSystemTable->ConIn->WaitForKey, &EventIndex);
|
||||||
|
BlReadKeyStroke(&Key);
|
||||||
|
|
||||||
|
/* Check key press scan code */
|
||||||
|
if(Key.UnicodeChar == 0x0D)
|
||||||
|
{
|
||||||
|
/* ENTER key pressed, edit the highlighted option */
|
||||||
|
OptionName = EditableOptions[HighligtedOptionId];
|
||||||
|
BlGetBootOptionValue(MenuEntry->Options, OptionName, &OriginalValue);
|
||||||
|
|
||||||
|
/* If the original value is NULL, use an empty string for editing */
|
||||||
|
if(OriginalValue == NULL)
|
||||||
|
{
|
||||||
|
ValueToEdit = L"";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ValueToEdit = OriginalValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Display input dialog to edit the option value */
|
||||||
|
NewValue = ValueToEdit;
|
||||||
|
BlDisplayInputDialog(OptionName, L"Enter new value:", &NewValue);
|
||||||
|
|
||||||
|
/* Check if the value was changed */
|
||||||
|
if(NewValue != ValueToEdit)
|
||||||
|
{
|
||||||
|
/* Update the boot option with the new value and free the old value */
|
||||||
|
BlSetBootOptionValue(MenuEntry->Options, OptionName, NewValue);
|
||||||
|
BlFreeMemoryPool(NewValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free the original value if it was allocated */
|
||||||
|
if(OriginalValue != NULL)
|
||||||
|
{
|
||||||
|
BlFreeMemoryPool(OriginalValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mark the edit menu for redraw */
|
||||||
|
RedrawEditMenu = TRUE;
|
||||||
|
}
|
||||||
|
else if(Key.ScanCode == 0x01)
|
||||||
|
{
|
||||||
|
/* UpArrow key pressed, go to previous entry if possible */
|
||||||
|
if(HighligtedOptionId > 0)
|
||||||
|
{
|
||||||
|
/* Highlight previous entry */
|
||||||
|
OldHighligtedOptionId = HighligtedOptionId;
|
||||||
|
HighligtedOptionId--;
|
||||||
|
|
||||||
|
/* Check if we need to scroll the view */
|
||||||
|
if(HighligtedOptionId < TopVisibleEntry)
|
||||||
|
{
|
||||||
|
/* Scroll the view */
|
||||||
|
TopVisibleEntry = HighligtedOptionId;
|
||||||
|
RedrawEntries = TRUE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Redraw old highlighted entry */
|
||||||
|
BlGetBootOptionValue(MenuEntry->Options, EditableOptions[OldHighligtedOptionId], &Value);
|
||||||
|
BlpDrawEditMenuEntry(&Handle, EditableOptions[OldHighligtedOptionId], Value, OldHighligtedOptionId - TopVisibleEntry, FALSE);
|
||||||
|
|
||||||
|
/* Free allocated value string if needed */
|
||||||
|
if(Value != NULL)
|
||||||
|
{
|
||||||
|
BlFreeMemoryPool(Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Redraw new highlighted entry */
|
||||||
|
BlGetBootOptionValue(MenuEntry->Options, EditableOptions[HighligtedOptionId], &Value);
|
||||||
|
BlpDrawEditMenuEntry(&Handle, EditableOptions[HighligtedOptionId], Value, HighligtedOptionId - TopVisibleEntry, TRUE);
|
||||||
|
|
||||||
|
/* Free allocated value string if needed */
|
||||||
|
if(Value != NULL)
|
||||||
|
{
|
||||||
|
BlFreeMemoryPool(Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(Key.ScanCode == 0x02)
|
||||||
|
{
|
||||||
|
/* DownArrow key pressed, go to next entry if possible */
|
||||||
|
if(HighligtedOptionId < NumberOfOptions - 1)
|
||||||
|
{
|
||||||
|
/* Highlight next entry */
|
||||||
|
OldHighligtedOptionId = HighligtedOptionId;
|
||||||
|
HighligtedOptionId++;
|
||||||
|
|
||||||
|
/* Check if we need to scroll the view */
|
||||||
|
if(HighligtedOptionId >= TopVisibleEntry + VisibleEntries)
|
||||||
|
{
|
||||||
|
/* Scroll the view */
|
||||||
|
TopVisibleEntry = HighligtedOptionId - VisibleEntries + 1;
|
||||||
|
RedrawEntries = TRUE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Redraw old highlighted entry */
|
||||||
|
BlGetBootOptionValue(MenuEntry->Options, EditableOptions[OldHighligtedOptionId], &Value);
|
||||||
|
BlpDrawEditMenuEntry(&Handle, EditableOptions[OldHighligtedOptionId], Value, OldHighligtedOptionId - TopVisibleEntry, FALSE);
|
||||||
|
|
||||||
|
/* Free allocated value string if needed */
|
||||||
|
if(Value != NULL)
|
||||||
|
{
|
||||||
|
BlFreeMemoryPool(Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Redraw new highlighted entry */
|
||||||
|
BlGetBootOptionValue(MenuEntry->Options, EditableOptions[HighligtedOptionId], &Value);
|
||||||
|
BlpDrawEditMenuEntry(&Handle, EditableOptions[HighligtedOptionId], Value, HighligtedOptionId - TopVisibleEntry, TRUE);
|
||||||
|
|
||||||
|
/* Free allocated value string if needed */
|
||||||
|
if(Value != NULL)
|
||||||
|
{
|
||||||
|
BlFreeMemoryPool(Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(Key.ScanCode == 0x09)
|
||||||
|
{
|
||||||
|
/* PageUp key pressed, go to top entry */
|
||||||
|
if(HighligtedOptionId != 0)
|
||||||
|
{
|
||||||
|
/* Highlight first entry */
|
||||||
|
HighligtedOptionId = 0;
|
||||||
|
TopVisibleEntry = 0;
|
||||||
|
RedrawEntries = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(Key.ScanCode == 0x0A)
|
||||||
|
{
|
||||||
|
/* PageDown key pressed, go to bottom entry */
|
||||||
|
if(HighligtedOptionId != NumberOfOptions - 1)
|
||||||
|
{
|
||||||
|
/* Highlight last entry */
|
||||||
|
HighligtedOptionId = NumberOfOptions - 1;
|
||||||
|
TopVisibleEntry = (NumberOfOptions > VisibleEntries) ? (NumberOfOptions - VisibleEntries) : 0;
|
||||||
|
RedrawEntries = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(Key.ScanCode == 0x17)
|
||||||
|
{
|
||||||
|
/* ESC key pressed, exit edit menu */
|
||||||
|
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.
|
||||||
*
|
*
|
||||||
@ -505,12 +729,11 @@ XTCDECL
|
|||||||
VOID
|
VOID
|
||||||
BlDisplayInputDialog(IN PWCHAR Caption,
|
BlDisplayInputDialog(IN PWCHAR Caption,
|
||||||
IN PWCHAR Message,
|
IN PWCHAR Message,
|
||||||
IN PWCHAR *InputFieldText)
|
IN OUT PWCHAR *InputFieldText)
|
||||||
{
|
{
|
||||||
SIZE_T InputFieldLength, TextCursorPosition, TextIndex, TextPosition;
|
SIZE_T InputFieldLength, TextCursorPosition, TextIndex, TextPosition;
|
||||||
XTBL_DIALOG_HANDLE Handle;
|
XTBL_DIALOG_HANDLE Handle;
|
||||||
PWCHAR InputFieldBuffer;
|
PWCHAR InputFieldBuffer;
|
||||||
SIZE_T BufferLength;
|
|
||||||
EFI_INPUT_KEY Key;
|
EFI_INPUT_KEY Key;
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
UINT_PTR Index;
|
UINT_PTR Index;
|
||||||
@ -535,9 +758,11 @@ BlDisplayInputDialog(IN PWCHAR Caption,
|
|||||||
Key.ScanCode = 0;
|
Key.ScanCode = 0;
|
||||||
Key.UnicodeChar = 0;
|
Key.UnicodeChar = 0;
|
||||||
|
|
||||||
/* Get initial input text length and allocate a buffer */
|
/* Determine input field length */
|
||||||
BufferLength = RtlWideStringLength(*InputFieldText, 0);
|
InputFieldLength = RtlWideStringLength(*InputFieldText, 0);
|
||||||
Status = BlAllocateMemoryPool(BufferLength * sizeof(WCHAR), (PVOID *)&InputFieldBuffer);
|
|
||||||
|
/* Allocate a buffer for storing the input field text */
|
||||||
|
Status = BlAllocateMemoryPool(2048 * sizeof(WCHAR), (PVOID *)&InputFieldBuffer);
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
{
|
{
|
||||||
/* Memory allocation failure, print error message and return */
|
/* Memory allocation failure, print error message and return */
|
||||||
@ -547,15 +772,8 @@ BlDisplayInputDialog(IN PWCHAR Caption,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Copy input text into edit buffer */
|
/* Copy input text into edit buffer */
|
||||||
RtlCopyMemory(InputFieldBuffer, *InputFieldText, BufferLength * sizeof(WCHAR));
|
RtlCopyMemory(InputFieldBuffer, *InputFieldText, InputFieldLength * sizeof(WCHAR));
|
||||||
InputFieldBuffer[BufferLength] = L'\0';
|
InputFieldBuffer[InputFieldLength] = L'\0';
|
||||||
|
|
||||||
/* Determine input field length */
|
|
||||||
InputFieldLength = BufferLength;
|
|
||||||
if(InputFieldLength > Handle.Width - 8)
|
|
||||||
{
|
|
||||||
InputFieldLength = Handle.Width - 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Start at first character */
|
/* Start at first character */
|
||||||
TextPosition = 0;
|
TextPosition = 0;
|
||||||
@ -618,12 +836,16 @@ BlDisplayInputDialog(IN PWCHAR Caption,
|
|||||||
/* DELETE key pressed, delete character */
|
/* DELETE key pressed, delete character */
|
||||||
if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT)
|
if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT)
|
||||||
{
|
{
|
||||||
|
/* Check if buffer is not empty */
|
||||||
if(InputFieldLength > 0 && TextPosition < InputFieldLength)
|
if(InputFieldLength > 0 && TextPosition < InputFieldLength)
|
||||||
{
|
{
|
||||||
|
/* Delete character */
|
||||||
RtlMoveMemory(InputFieldBuffer + TextPosition, InputFieldBuffer + TextPosition + 1,
|
RtlMoveMemory(InputFieldBuffer + TextPosition, InputFieldBuffer + TextPosition + 1,
|
||||||
(InputFieldLength - TextPosition) * sizeof(WCHAR));
|
(InputFieldLength - TextPosition) * sizeof(WCHAR));
|
||||||
|
|
||||||
|
/* Decrement length and null terminate string */
|
||||||
InputFieldLength--;
|
InputFieldLength--;
|
||||||
InputFieldBuffer[InputFieldLength] = 0;
|
InputFieldBuffer[InputFieldLength] = L'\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -632,13 +854,17 @@ BlDisplayInputDialog(IN PWCHAR Caption,
|
|||||||
/* BACKSPACE key pressed, delete character */
|
/* BACKSPACE key pressed, delete character */
|
||||||
if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT)
|
if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT)
|
||||||
{
|
{
|
||||||
|
/* Check if buffer is not empty */
|
||||||
if(InputFieldLength > 0 && TextPosition > 0 && TextPosition <= InputFieldLength)
|
if(InputFieldLength > 0 && TextPosition > 0 && TextPosition <= InputFieldLength)
|
||||||
{
|
{
|
||||||
TextPosition--;
|
/* Delete character */
|
||||||
RtlMoveMemory(InputFieldBuffer + TextPosition, InputFieldBuffer + TextPosition + 1,
|
RtlMoveMemory(InputFieldBuffer + TextPosition, InputFieldBuffer + TextPosition + 1,
|
||||||
(InputFieldLength - TextPosition) * sizeof(WCHAR));
|
(InputFieldLength - TextPosition) * sizeof(WCHAR));
|
||||||
|
|
||||||
|
/* Decrement length, position and null terminate string */
|
||||||
|
TextPosition--;
|
||||||
InputFieldLength--;
|
InputFieldLength--;
|
||||||
InputFieldBuffer[InputFieldLength] = 0;
|
InputFieldBuffer[InputFieldLength] = L'\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -653,15 +879,23 @@ BlDisplayInputDialog(IN PWCHAR Caption,
|
|||||||
/* Other key pressed, add character to the buffer */
|
/* Other key pressed, add character to the buffer */
|
||||||
if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT && Key.UnicodeChar != 0)
|
if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT && Key.UnicodeChar != 0)
|
||||||
{
|
{
|
||||||
RtlMoveMemory(InputFieldBuffer + TextPosition + 1, InputFieldBuffer + TextPosition,
|
/* Check if buffer is full */
|
||||||
(InputFieldLength - TextPosition) * sizeof(WCHAR));
|
if(InputFieldLength < 2047)
|
||||||
InputFieldBuffer[TextPosition] = Key.UnicodeChar;
|
{
|
||||||
TextPosition++;
|
/* Insert character at current position */
|
||||||
InputFieldLength++;
|
RtlMoveMemory(InputFieldBuffer + TextPosition + 1, InputFieldBuffer + TextPosition,
|
||||||
InputFieldBuffer[InputFieldLength] = 0;
|
(InputFieldLength - TextPosition) * sizeof(WCHAR));
|
||||||
|
InputFieldBuffer[TextPosition] = Key.UnicodeChar;
|
||||||
|
|
||||||
|
/* Increment length, position and null terminate string */
|
||||||
|
TextPosition++;
|
||||||
|
InputFieldLength++;
|
||||||
|
InputFieldBuffer[InputFieldLength] = L'\0';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Calculate text index and cursor position */
|
||||||
if(TextPosition > (Handle.Width - 9))
|
if(TextPosition > (Handle.Width - 9))
|
||||||
{
|
{
|
||||||
TextIndex = TextPosition - (Handle.Width - 9);
|
TextIndex = TextPosition - (Handle.Width - 9);
|
||||||
@ -677,6 +911,7 @@ BlDisplayInputDialog(IN PWCHAR Caption,
|
|||||||
BlpDrawDialogButton(&Handle);
|
BlpDrawDialogButton(&Handle);
|
||||||
BlpDrawDialogInputField(&Handle, &InputFieldBuffer[TextIndex]);
|
BlpDrawDialogInputField(&Handle, &InputFieldBuffer[TextIndex]);
|
||||||
|
|
||||||
|
/* Set cursor position if input field is active */
|
||||||
if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT)
|
if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT)
|
||||||
{
|
{
|
||||||
BlSetCursorPosition(Handle.PosX + 4 + TextCursorPosition, Handle.PosY + Handle.Height - 4);
|
BlSetCursorPosition(Handle.PosX + 4 + TextCursorPosition, Handle.PosY + Handle.Height - 4);
|
||||||
@ -1395,3 +1630,164 @@ BlpDrawDialogProgressBar(IN PXTBL_DIALOG_HANDLE Handle,
|
|||||||
BlDisableConsoleCursor();
|
BlDisableConsoleCursor();
|
||||||
BlConsoleWrite(ProgressBar);
|
BlConsoleWrite(ProgressBar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws a text-based boot edition menu.
|
||||||
|
*
|
||||||
|
* @param Handle
|
||||||
|
* Supplies a pointer to the edition menu handle.
|
||||||
|
*
|
||||||
|
* @return This function does not return any value.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTCDECL
|
||||||
|
VOID
|
||||||
|
BlpDrawEditMenu(OUT PXTBL_DIALOG_HANDLE Handle)
|
||||||
|
{
|
||||||
|
/* Query console screen resolution */
|
||||||
|
BlQueryConsoleMode(&Handle->ResX, &Handle->ResY);
|
||||||
|
|
||||||
|
/* Set boot menu parameters */
|
||||||
|
Handle->Attributes = 0;
|
||||||
|
Handle->DialogColor = EFI_TEXT_BGCOLOR_BLACK;
|
||||||
|
Handle->TextColor = EFI_TEXT_FGCOLOR_LIGHTGRAY;
|
||||||
|
Handle->PosX = 3;
|
||||||
|
Handle->PosY = 3;
|
||||||
|
Handle->Width = Handle->ResX - 6;
|
||||||
|
Handle->Height = Handle->ResY - 10;
|
||||||
|
|
||||||
|
/* Clear screen and disable cursor */
|
||||||
|
BlSetConsoleAttributes(Handle->DialogColor | Handle->TextColor);
|
||||||
|
BlClearConsoleScreen();
|
||||||
|
BlDisableConsoleCursor();
|
||||||
|
|
||||||
|
/* Check if debugging enabled */
|
||||||
|
if(DEBUG)
|
||||||
|
{
|
||||||
|
/* Print debug version of XTLDR banner */
|
||||||
|
BlSetCursorPosition((Handle->ResX - 44) / 2, 1);
|
||||||
|
BlConsolePrint(L"XTLDR Boot Loader v%d.%d (%s-%s)\n",
|
||||||
|
XTLDR_VERSION_MAJOR, XTLDR_VERSION_MINOR, XTOS_VERSION_DATE, XTOS_VERSION_HASH);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Print standard XTLDR banner */
|
||||||
|
BlSetCursorPosition((Handle->ResX - 22) / 2, 1);
|
||||||
|
BlConsolePrint(L"XTLDR Boot Loader v%d.%d\n", XTLDR_VERSION_MAJOR, XTLDR_VERSION_MINOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw empty dialog box for boot menu */
|
||||||
|
BlpDrawDialogBox(Handle, L"Edit Options", NULL);
|
||||||
|
|
||||||
|
/* Print help message below the edit menu */
|
||||||
|
BlSetCursorPosition(0, Handle->PosY + Handle->Height);
|
||||||
|
BlSetConsoleAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY);
|
||||||
|
BlConsolePrint(L" Use cursors to change the selection. Press ENTER key to edit the chosen\n"
|
||||||
|
L" option or ESC to return to the main boot menu.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws edit menu entry at the specified position.
|
||||||
|
*
|
||||||
|
* @param Handle
|
||||||
|
* Supplies a pointer to the boot menu handle.
|
||||||
|
*
|
||||||
|
* @param OptionName
|
||||||
|
* Supplies a pointer to the buffer containing a part of the menu entry name (an option name).
|
||||||
|
*
|
||||||
|
* @param OptionValue
|
||||||
|
* Supplies a pointer to the buffer containing a part of the menu entry name (an option value).
|
||||||
|
*
|
||||||
|
* @param Position
|
||||||
|
* Specifies entry position on the list in the boot menu.
|
||||||
|
*
|
||||||
|
* @param Highlighted
|
||||||
|
* Specifies whether this entry should be highlighted or not.
|
||||||
|
*
|
||||||
|
* @return This routine does not return any value.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTCDECL
|
||||||
|
EFI_STATUS
|
||||||
|
BlpDrawEditMenuEntry(IN PXTBL_DIALOG_HANDLE Handle,
|
||||||
|
IN PWCHAR OptionName,
|
||||||
|
IN PWCHAR OptionValue,
|
||||||
|
IN UINT Position,
|
||||||
|
IN BOOLEAN Highlighted)
|
||||||
|
{
|
||||||
|
BOOLEAN Allocation;
|
||||||
|
PWCHAR DisplayValue, ShortValue;
|
||||||
|
UINT Index;
|
||||||
|
ULONG OptionNameLength, OptionValueLength, OptionWidth;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
/* Assume no allocation was made */
|
||||||
|
Allocation = FALSE;
|
||||||
|
|
||||||
|
/* Set display value depending on input */
|
||||||
|
DisplayValue = (OptionValue != NULL) ? OptionValue : L"";
|
||||||
|
|
||||||
|
/* Determine lengths */
|
||||||
|
OptionNameLength = RtlWideStringLength(OptionName, 0);
|
||||||
|
OptionValueLength = RtlWideStringLength(DisplayValue, 0);
|
||||||
|
OptionWidth = Handle->Width - 4 - (OptionNameLength + 2);
|
||||||
|
|
||||||
|
/* Check if value needs to be truncated */
|
||||||
|
if(OptionValueLength > OptionWidth)
|
||||||
|
{
|
||||||
|
/* Allocate buffer for new, shortened value */
|
||||||
|
Status = BlAllocateMemoryPool((OptionWidth + 1) * sizeof(WCHAR), (PVOID *)&ShortValue);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Memory allocation failure, print debug message and return */
|
||||||
|
BlDebugPrint(L"ERROR: Memory allocation failure (Status Code: 0x%zX)\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy a desired value length into the allocated buffer and append "..." */
|
||||||
|
RtlCopyMemory(ShortValue, DisplayValue, (OptionWidth - 3) * sizeof(WCHAR));
|
||||||
|
RtlCopyMemory(ShortValue + OptionWidth - 3, L"...", 3 * sizeof(WCHAR));
|
||||||
|
ShortValue[OptionWidth] = L'\0';
|
||||||
|
|
||||||
|
/* Mark that allocation was made and set new display value */
|
||||||
|
Allocation = TRUE;
|
||||||
|
DisplayValue = ShortValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move cursor to the right position */
|
||||||
|
BlSetCursorPosition(5, 4 + Position);
|
||||||
|
|
||||||
|
/* Check whether this entry should be highlighted */
|
||||||
|
if(Highlighted)
|
||||||
|
{
|
||||||
|
/* Highlight this entry */
|
||||||
|
BlSetConsoleAttributes(EFI_TEXT_BGCOLOR_LIGHTGRAY | EFI_TEXT_FGCOLOR_BLACK);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set default colors */
|
||||||
|
BlSetConsoleAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear menu entry */
|
||||||
|
for(Index = 0; Index < Handle->Width - 4; Index++)
|
||||||
|
{
|
||||||
|
BlConsolePrint(L" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print menu entry */
|
||||||
|
BlSetCursorPosition(5, 4 + Position);
|
||||||
|
BlConsolePrint(L"%S: %S", OptionName, DisplayValue);
|
||||||
|
|
||||||
|
/* Check if allocation was made */
|
||||||
|
if(Allocation)
|
||||||
|
{
|
||||||
|
/* Free allocated memory */
|
||||||
|
BlFreeMemoryPool(DisplayValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return success */
|
||||||
|
return STATUS_EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user