/** @file\r
Hotkey library functions.\r
\r
-Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
EFI_BOOT_MANAGER_KEY_OPTION *mBmContinueKeyOption = NULL;\r
VOID *mBmTxtInExRegistration = NULL;\r
\r
+\r
+/**\r
+ Return the buffer size of the EFI_BOOT_MANAGER_KEY_OPTION data.\r
+\r
+ @param KeyOption The input key option info.\r
+\r
+ @retval The buffer size of the key option data.\r
+**/\r
+UINTN\r
+BmSizeOfKeyOption (\r
+ IN CONST EFI_BOOT_MANAGER_KEY_OPTION *KeyOption\r
+ )\r
+{\r
+ return OFFSET_OF (EFI_BOOT_MANAGER_KEY_OPTION, Keys)\r
+ + KeyOption->KeyData.Options.InputKeyCount * sizeof (EFI_INPUT_KEY);\r
+}\r
+\r
/**\r
\r
Check whether the input key option is valid.\r
\r
- @param KeyOption Input key option info.\r
+ @param KeyOption Key option.\r
+ @param KeyOptionSize Size of the key option.\r
\r
@retval TRUE Input key option is valid.\r
@retval FALSE Input key option is not valid.\r
**/\r
BOOLEAN\r
BmIsKeyOptionValid (\r
- IN EFI_BOOT_MANAGER_KEY_OPTION *KeyOption\r
+ IN CONST EFI_BOOT_MANAGER_KEY_OPTION *KeyOption,\r
+ IN UINTN KeyOptionSize\r
)\r
{\r
- UINT16 OptionName[sizeof (L"Boot####")];\r
+ UINT16 OptionName[BM_OPTION_NAME_LEN];\r
UINT8 *BootOption;\r
UINTN BootOptionSize;\r
UINT32 Crc;\r
\r
+ if (BmSizeOfKeyOption (KeyOption) != KeyOptionSize) {\r
+ return FALSE;\r
+ }\r
+\r
//\r
// Check whether corresponding Boot Option exist\r
//\r
- UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", KeyOption->BootOption);\r
+ UnicodeSPrint (\r
+ OptionName, sizeof (OptionName), L"%s%04x",\r
+ mBmLoadOptionName[LoadOptionTypeBoot], KeyOption->BootOption\r
+ );\r
GetEfiGlobalVariable2 (OptionName, (VOID **) &BootOption, &BootOptionSize);\r
\r
if (BootOption == NULL) {\r
)\r
{\r
UINTN Index;\r
- \r
+ UINTN Uint;\r
+\r
if (!CompareGuid (Guid, &gEfiGlobalVariableGuid) ||\r
(StrSize (Name) != sizeof (L"Key####")) ||\r
(StrnCmp (Name, L"Key", 3) != 0)\r
\r
*OptionNumber = 0;\r
for (Index = 3; Index < 7; Index++) {\r
- if ((Name[Index] >= L'0') && (Name[Index] <= L'9')) {\r
- *OptionNumber = *OptionNumber * 16 + Name[Index] - L'0';\r
- } else if ((Name[Index] >= L'A') && (Name[Index] <= L'F')) {\r
- *OptionNumber = *OptionNumber * 16 + Name[Index] - L'A' + 10;\r
- } else {\r
+ Uint = BmCharToUint (Name[Index]);\r
+ if (Uint == -1) {\r
return FALSE;\r
+ } else {\r
+ *OptionNumber = (UINT16) Uint + *OptionNumber * 0x10;\r
}\r
}\r
\r
return TRUE;\r
}\r
\r
-/**\r
- Return the buffer size of the EFI_BOOT_MANAGER_KEY_OPTION data.\r
+typedef struct {\r
+ EFI_BOOT_MANAGER_KEY_OPTION *KeyOptions;\r
+ UINTN KeyOptionCount;\r
+} BM_COLLECT_KEY_OPTIONS_PARAM;\r
\r
- @param KeyOption The input key option info.\r
+/**\r
+ Visitor function to collect the key options from NV storage.\r
\r
- @retval The buffer size of the key option data.\r
+ @param Name Variable name.\r
+ @param Guid Variable GUID.\r
+ @param Context The same context passed to BmForEachVariable.\r
**/\r
-UINTN\r
-BmSizeOfKeyOption (\r
- EFI_BOOT_MANAGER_KEY_OPTION *KeyOption\r
+VOID\r
+BmCollectKeyOptions (\r
+ CHAR16 *Name,\r
+ EFI_GUID *Guid,\r
+ VOID *Context\r
)\r
{\r
- return OFFSET_OF (EFI_BOOT_MANAGER_KEY_OPTION, Keys)\r
- + KeyOption->KeyData.Options.InputKeyCount * sizeof (EFI_INPUT_KEY);\r
+ UINTN Index;\r
+ BM_COLLECT_KEY_OPTIONS_PARAM *Param;\r
+ VOID *KeyOption;\r
+ UINT16 OptionNumber;\r
+ UINTN KeyOptionSize;\r
+\r
+ Param = (BM_COLLECT_KEY_OPTIONS_PARAM *) Context;\r
+\r
+ if (BmIsKeyOptionVariable (Name, Guid, &OptionNumber)) {\r
+ GetEfiGlobalVariable2 (Name, &KeyOption, &KeyOptionSize);\r
+ ASSERT (KeyOption != NULL);\r
+ if (BmIsKeyOptionValid (KeyOption, KeyOptionSize)) {\r
+ Param->KeyOptions = ReallocatePool (\r
+ Param->KeyOptionCount * sizeof (EFI_BOOT_MANAGER_KEY_OPTION),\r
+ (Param->KeyOptionCount + 1) * sizeof (EFI_BOOT_MANAGER_KEY_OPTION),\r
+ Param->KeyOptions\r
+ );\r
+ ASSERT (Param->KeyOptions != NULL);\r
+ //\r
+ // Insert the key option in order\r
+ //\r
+ for (Index = 0; Index < Param->KeyOptionCount; Index++) {\r
+ if (OptionNumber < Param->KeyOptions[Index].OptionNumber) {\r
+ break;\r
+ }\r
+ }\r
+ CopyMem (&Param->KeyOptions[Index + 1], &Param->KeyOptions[Index], (Param->KeyOptionCount - Index) * sizeof (EFI_BOOT_MANAGER_KEY_OPTION));\r
+ CopyMem (&Param->KeyOptions[Index], KeyOption, KeyOptionSize);\r
+ Param->KeyOptions[Index].OptionNumber = OptionNumber;\r
+ Param->KeyOptionCount++;\r
+ }\r
+ FreePool (KeyOption);\r
+ }\r
}\r
\r
/**\r
OUT UINTN *Count\r
)\r
{\r
- EFI_STATUS Status;\r
- UINTN Index;\r
- CHAR16 *Name;\r
- EFI_GUID Guid;\r
- UINTN NameSize;\r
- UINTN NewNameSize;\r
- EFI_BOOT_MANAGER_KEY_OPTION *KeyOptions;\r
- EFI_BOOT_MANAGER_KEY_OPTION *KeyOption;\r
- UINT16 OptionNumber;\r
+ BM_COLLECT_KEY_OPTIONS_PARAM Param;\r
\r
if (Count == NULL) {\r
return NULL;\r
}\r
\r
- *Count = 0;\r
- KeyOptions = NULL;\r
+ Param.KeyOptions = NULL;\r
+ Param.KeyOptionCount = 0;\r
\r
- NameSize = sizeof (CHAR16);\r
- Name = AllocateZeroPool (NameSize);\r
- ASSERT (Name != NULL);\r
- while (TRUE) {\r
- NewNameSize = NameSize;\r
- Status = gRT->GetNextVariableName (&NewNameSize, Name, &Guid);\r
- if (Status == EFI_BUFFER_TOO_SMALL) {\r
- Name = ReallocatePool (NameSize, NewNameSize, Name);\r
- ASSERT (Name != NULL);\r
- Status = gRT->GetNextVariableName (&NewNameSize, Name, &Guid);\r
- NameSize = NewNameSize;\r
- }\r
+ BmForEachVariable (BmCollectKeyOptions, (VOID *) &Param);\r
\r
- if (Status == EFI_NOT_FOUND) {\r
- break;\r
- }\r
- ASSERT_EFI_ERROR (Status);\r
+ *Count = Param.KeyOptionCount;\r
\r
- if (BmIsKeyOptionVariable (Name ,&Guid, &OptionNumber)) {\r
- GetEfiGlobalVariable2 (Name, (VOID**) &KeyOption, NULL);\r
- ASSERT (KeyOption != NULL);\r
- if (BmIsKeyOptionValid (KeyOption)) {\r
- KeyOptions = ReallocatePool (\r
- *Count * sizeof (EFI_BOOT_MANAGER_KEY_OPTION),\r
- (*Count + 1) * sizeof (EFI_BOOT_MANAGER_KEY_OPTION),\r
- KeyOptions\r
- );\r
- ASSERT (KeyOptions != NULL);\r
- //\r
- // Insert the key option in order\r
- //\r
- for (Index = 0; Index < *Count; Index++) {\r
- if (OptionNumber < KeyOptions[Index].OptionNumber) {\r
- break;\r
- }\r
- }\r
- CopyMem (&KeyOptions[Index + 1], &KeyOptions[Index], (*Count - Index) * sizeof (EFI_BOOT_MANAGER_KEY_OPTION));\r
- CopyMem (&KeyOptions[Index], KeyOption, BmSizeOfKeyOption (KeyOption));\r
- KeyOptions[Index].OptionNumber = OptionNumber;\r
- (*Count)++;\r
- }\r
- FreePool (KeyOption);\r
- }\r
- }\r
-\r
- FreePool (Name);\r
-\r
- return KeyOptions;\r
-}\r
-\r
-/**\r
- Callback function for event.\r
- \r
- @param Event Event for this callback function.\r
- @param Context Context pass to this function.\r
-**/\r
-VOID\r
-EFIAPI\r
-BmEmptyFunction (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
+ return Param.KeyOptions;\r
}\r
\r
/**\r
{\r
LIST_ENTRY *Link;\r
BM_HOTKEY *Hotkey;\r
- CHAR16 OptionName[sizeof ("Boot####")];\r
+ CHAR16 OptionName[BM_OPTION_NAME_LEN];\r
EFI_STATUS Status;\r
EFI_KEY_DATA *HotkeyData;\r
\r
HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey];\r
if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) &&\r
(KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) &&\r
- (((KeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) ? \r
+ (((KeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) ?\r
(KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : TRUE\r
)\r
) {\r
//\r
// Launch its BootOption\r
//\r
- UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", Hotkey->BootOption);\r
+ UnicodeSPrint (\r
+ OptionName, sizeof (OptionName), L"%s%04x",\r
+ mBmLoadOptionName[LoadOptionTypeBoot], Hotkey->BootOption\r
+ );\r
Status = EfiBootManagerVariableToLoadOption (OptionName, &mBmHotkeyBootOption);\r
DEBUG ((EFI_D_INFO, "[Bds]Hotkey for %s pressed - %r\n", OptionName, Status));\r
if (EFI_ERROR (Status)) {\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Return the active Simple Text Input Ex handle array.\r
+ If the SystemTable.ConsoleInHandle is NULL, the function returns all\r
+ founded Simple Text Input Ex handles.\r
+ Otherwise, it just returns the ConsoleInHandle.\r
+\r
+ @param Count Return the handle count.\r
+\r
+ @retval The active console handles.\r
+**/\r
+EFI_HANDLE *\r
+BmGetActiveConsoleIn (\r
+ OUT UINTN *Count\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE *Handles;\r
+\r
+ Handles = NULL;\r
+ *Count = 0;\r
+\r
+ if (gST->ConsoleInHandle != NULL) {\r
+ Status = gBS->OpenProtocol (\r
+ gST->ConsoleInHandle,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ NULL,\r
+ gImageHandle,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Handles = AllocateCopyPool (sizeof (EFI_HANDLE), &gST->ConsoleInHandle);\r
+ if (Handles != NULL) {\r
+ *Count = 1;\r
+ }\r
+ }\r
+ } else {\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ NULL,\r
+ Count,\r
+ &Handles\r
+ );\r
+ }\r
+\r
+ return Handles;\r
+}\r
+\r
/**\r
Unregister hotkey notify list.\r
\r
EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TxtInEx;\r
VOID *NotifyHandle;\r
\r
- gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- &gEfiSimpleTextInputExProtocolGuid,\r
- NULL,\r
- &HandleCount,\r
- &Handles\r
- );\r
+ Handles = BmGetActiveConsoleIn (&HandleCount);\r
for (Index = 0; Index < HandleCount; Index++) {\r
Status = gBS->HandleProtocol (Handles[Index], &gEfiSimpleTextInputExProtocolGuid, (VOID **) &TxtInEx);\r
ASSERT_EFI_ERROR (Status);\r
}\r
}\r
\r
+ if (Handles != NULL) {\r
+ FreePool (Handles);\r
+ }\r
+\r
return EFI_SUCCESS;\r
}\r
\r
\r
KeyShiftStateCount = 0;\r
BmGenerateKeyShiftState (0, KeyOption, EFI_SHIFT_STATE_VALID, KeyShiftStates, &KeyShiftStateCount);\r
- ASSERT (KeyShiftStateCount <= sizeof (KeyShiftStates) / sizeof (KeyShiftStates[0]));\r
+ ASSERT (KeyShiftStateCount <= ARRAY_SIZE (KeyShiftStates));\r
\r
EfiAcquireLock (&mBmHotkeyLock);\r
\r
+ Handles = BmGetActiveConsoleIn (&HandleCount);\r
+\r
for (Index = 0; Index < KeyShiftStateCount; Index++) {\r
Hotkey = AllocateZeroPool (sizeof (BM_HOTKEY));\r
ASSERT (Hotkey != NULL);\r
}\r
InsertTailList (&mBmHotkeyList, &Hotkey->Link);\r
\r
- gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- &gEfiSimpleTextInputExProtocolGuid,\r
- NULL,\r
- &HandleCount,\r
- &Handles\r
- );\r
for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {\r
Status = gBS->HandleProtocol (Handles[HandleIndex], &gEfiSimpleTextInputExProtocolGuid, (VOID **) &TxtInEx);\r
ASSERT_EFI_ERROR (Status);\r
}\r
}\r
\r
+ if (Handles != NULL) {\r
+ FreePool (Handles);\r
+ }\r
EfiReleaseLock (&mBmHotkeyLock);\r
\r
return EFI_SUCCESS;\r
EFI_STATUS Status;\r
EFI_BOOT_MANAGER_KEY_OPTION KeyOption;\r
VA_LIST Args;\r
- \r
+\r
if (mBmContinueKeyOption != NULL) {\r
return EFI_ALREADY_STARTED;\r
}\r
\r
/**\r
Stop the hotkey processing.\r
- \r
+\r
@param Event Event pointer related to hotkey service.\r
@param Context Context pass to this function.\r
**/\r
/**\r
Start the hot key service so that the key press can trigger the boot option.\r
\r
- @param HotkeyTriggered Return the waitable event and it will be signaled \r
+ @param HotkeyTriggered Return the waitable event and it will be signaled\r
when a valid hot key is pressed.\r
\r
@retval EFI_SUCCESS The hot key service is started.\r
EFI_EVENT Event;\r
UINT32 *BootOptionSupport;\r
\r
- Status = GetEfiGlobalVariable2 (EFI_BOOT_OPTION_SUPPORT_VARIABLE_NAME, (VOID **) &BootOptionSupport, NULL);\r
- ASSERT (BootOptionSupport != NULL);\r
-\r
- if ((*BootOptionSupport & EFI_BOOT_OPTION_SUPPORT_KEY) != 0) {\r
- mBmHotkeySupportCount = ((*BootOptionSupport & EFI_BOOT_OPTION_SUPPORT_COUNT) >> LowBitSet32 (EFI_BOOT_OPTION_SUPPORT_COUNT));\r
+ GetEfiGlobalVariable2 (EFI_BOOT_OPTION_SUPPORT_VARIABLE_NAME, (VOID **) &BootOptionSupport, NULL);\r
+ if (BootOptionSupport != NULL) {\r
+ if ((*BootOptionSupport & EFI_BOOT_OPTION_SUPPORT_KEY) != 0) {\r
+ mBmHotkeySupportCount = ((*BootOptionSupport & EFI_BOOT_OPTION_SUPPORT_COUNT) >> LowBitSet32 (EFI_BOOT_OPTION_SUPPORT_COUNT));\r
+ }\r
+ FreePool (BootOptionSupport);\r
}\r
- FreePool (BootOptionSupport);\r
\r
if (mBmHotkeySupportCount == 0) {\r
DEBUG ((EFI_D_INFO, "Bds: BootOptionSupport NV variable forbids starting the hotkey service.\n"));\r
Status = gBS->CreateEvent (\r
EVT_NOTIFY_WAIT,\r
TPL_CALLBACK,\r
- BmEmptyFunction,\r
+ EfiEventEmptyFunction,\r
NULL,\r
&mBmHotkeyTriggered\r
);\r
BmProcessKeyOption (mBmContinueKeyOption);\r
}\r
\r
- EfiCreateProtocolNotifyEvent (\r
- &gEfiSimpleTextInputExProtocolGuid,\r
- TPL_CALLBACK,\r
- BmTxtInExCallback,\r
- NULL,\r
- &mBmTxtInExRegistration\r
- );\r
+ //\r
+ // Hook hotkey on every future SimpleTextInputEx instance when\r
+ // SystemTable.ConsoleInHandle == NULL, which means the console\r
+ // manager (ConSplitter) is absent.\r
+ //\r
+ if (gST->ConsoleInHandle == NULL) {\r
+ EfiCreateProtocolNotifyEvent (\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ TPL_CALLBACK,\r
+ BmTxtInExCallback,\r
+ NULL,\r
+ &mBmTxtInExRegistration\r
+ );\r
+ }\r
\r
Status = EfiCreateEventReadyToBootEx (\r
TPL_CALLBACK,\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
-\r
mBmHotkeyServiceStarted = TRUE;\r
return Status;\r
}\r
VA_LIST Args;\r
VOID *BootOption;\r
UINTN BootOptionSize;\r
- CHAR16 BootOptionName[sizeof (L"Boot####")];\r
+ CHAR16 BootOptionName[BM_OPTION_NAME_LEN];\r
EFI_BOOT_MANAGER_KEY_OPTION KeyOption;\r
EFI_BOOT_MANAGER_KEY_OPTION *KeyOptions;\r
UINTN KeyOptionCount;\r
UINTN Index;\r
UINTN KeyOptionNumber;\r
- CHAR16 KeyOptionName[sizeof (L"Key####")];\r
+ CHAR16 KeyOptionName[sizeof ("Key####")];\r
\r
- UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", BootOptionNumber);\r
+ UnicodeSPrint (\r
+ BootOptionName, sizeof (BootOptionName), L"%s%04x",\r
+ mBmLoadOptionName[LoadOptionTypeBoot], BootOptionNumber\r
+ );\r
GetEfiGlobalVariable2 (BootOptionName, &BootOption, &BootOptionSize);\r
\r
if (BootOption == NULL) {\r
BM_HOTKEY *Hotkey;\r
UINT32 ShiftState;\r
BOOLEAN Match;\r
- CHAR16 KeyOptionName[sizeof (L"Key####")];\r
+ CHAR16 KeyOptionName[sizeof ("Key####")];\r
\r
ZeroMem (&KeyOption, sizeof (EFI_BOOT_MANAGER_KEY_OPTION));\r
VA_START (Args, Modifier);\r