/** @file\r
Hotkey library functions.\r
\r
-Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2011 - 2017, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP<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
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
+ 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 EFI_BOOT_MANAGER_KEY_OPTION *KeyOption,\r
+ IN UINTN KeyOptionSize\r
)\r
{\r
UINT16 OptionName[BM_OPTION_NAME_LEN];\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
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
+ EFI_BOOT_MANAGER_KEY_OPTION *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, (VOID**) &KeyOption, &KeyOptionSize);\r
+ ASSERT (KeyOption != NULL);\r
+ KeyOption->OptionNumber = OptionNumber;\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 (KeyOption->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, BmSizeOfKeyOption (KeyOption));\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
-\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
-\r
- if (Status == EFI_NOT_FOUND) {\r
- break;\r
- }\r
- ASSERT_EFI_ERROR (Status);\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
+ Param.KeyOptions = NULL;\r
+ Param.KeyOptionCount = 0;\r
\r
- FreePool (Name);\r
+ BmForEachVariable (BmCollectKeyOptions, (VOID *) &Param);\r
\r
- return KeyOptions;\r
-}\r
+ *Count = Param.KeyOptionCount;\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
// 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
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
UINTN KeyOptionNumber;\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