-/**\r
- Create Key#### for the given hotkey.\r
-\r
- @param KeyOption The Hot Key Option to be added.\r
- @param KeyOptionNumber The key option number for Key#### (optional).\r
-\r
- @retval EFI_SUCCESS Register hotkey successfully.\r
- @retval EFI_INVALID_PARAMETER The hotkey option is invalid.\r
- @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource.\r
-\r
-**/\r
-EFI_STATUS\r
-RegisterHotkey (\r
- IN EFI_KEY_OPTION *KeyOption,\r
- OUT UINT16 *KeyOptionNumber\r
-)\r
-{\r
- UINT16 KeyOptionName[10];\r
- UINT16 *KeyOrder;\r
- UINTN KeyOrderSize;\r
- UINT16 *NewKeyOrder;\r
- UINTN Index;\r
- UINT16 MaxOptionNumber;\r
- UINT16 RegisterOptionNumber;\r
- EFI_KEY_OPTION *TempOption;\r
- UINTN TempOptionSize;\r
- EFI_STATUS Status;\r
- UINTN KeyOptionSize;\r
- BOOLEAN UpdateBootOption;\r
-\r
- //\r
- // Validate the given key option\r
- //\r
- if (!IsKeyOptionValid (KeyOption)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- KeyOptionSize = sizeof (EFI_KEY_OPTION) + KeyOption->KeyData.Options.InputKeyCount * sizeof (EFI_INPUT_KEY);\r
- UpdateBootOption = FALSE;\r
-\r
- //\r
- // Check whether HotKey conflict with keys used by Setup Browser\r
- //\r
- KeyOrder = BdsLibGetVariableAndSize (\r
- VAR_KEY_ORDER,\r
- &gEfiGlobalVariableGuid,\r
- &KeyOrderSize\r
- );\r
- if (KeyOrder == NULL) {\r
- KeyOrderSize = 0;\r
- }\r
-\r
- //\r
- // Find free key option number\r
- //\r
- MaxOptionNumber = 0;\r
- TempOption = NULL;\r
- for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index++) {\r
- if (MaxOptionNumber < KeyOrder[Index]) {\r
- MaxOptionNumber = KeyOrder[Index];\r
- }\r
-\r
- UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOrder[Index]);\r
- TempOption = BdsLibGetVariableAndSize (\r
- KeyOptionName,\r
- &gEfiGlobalVariableGuid,\r
- &TempOptionSize\r
- );\r
- ASSERT (TempOption != NULL);\r
-\r
- if (CompareMem (TempOption, KeyOption, TempOptionSize) == 0) {\r
- //\r
- // Got the option, so just return\r
- //\r
- FreePool (TempOption);\r
- FreePool (KeyOrder);\r
- return EFI_SUCCESS;\r
- }\r
-\r
- if (KeyOption->KeyData.PackedValue == TempOption->KeyData.PackedValue) {\r
- if (KeyOption->KeyData.Options.InputKeyCount == 0 ||\r
- CompareMem (\r
- ((UINT8 *) TempOption) + sizeof (EFI_KEY_OPTION),\r
- ((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION),\r
- KeyOptionSize - sizeof (EFI_KEY_OPTION)\r
- ) == 0) {\r
- //\r
- // Hotkey is the same but BootOption changed, need update\r
- //\r
- UpdateBootOption = TRUE;\r
- break;\r
- }\r
- }\r
-\r
- FreePool (TempOption);\r
- }\r
-\r
- if (UpdateBootOption) {\r
- RegisterOptionNumber = KeyOrder[Index];\r
- FreePool (TempOption);\r
- } else {\r
- RegisterOptionNumber = (UINT16) (MaxOptionNumber + 1);\r
- }\r
-\r
- if (KeyOptionNumber != NULL) {\r
- *KeyOptionNumber = RegisterOptionNumber;\r
- }\r
-\r
- //\r
- // Create variable Key####\r
- //\r
- UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", RegisterOptionNumber);\r
- Status = gRT->SetVariable (\r
- KeyOptionName,\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
- KeyOptionSize,\r
- KeyOption\r
- );\r
- if (EFI_ERROR (Status)) {\r
- FreePool (KeyOrder);\r
- return Status;\r
- }\r
-\r
- //\r
- // Update the key order variable - "KeyOrder"\r
- //\r
- if (!UpdateBootOption) {\r
- Index = KeyOrderSize / sizeof (UINT16);\r
- KeyOrderSize += sizeof (UINT16);\r
- }\r
-\r
- NewKeyOrder = AllocatePool (KeyOrderSize);\r
- if (NewKeyOrder == NULL) {\r
- FreePool (KeyOrder);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- if (KeyOrder != NULL) {\r
- CopyMem (NewKeyOrder, KeyOrder, KeyOrderSize);\r
- }\r
-\r
- NewKeyOrder[Index] = RegisterOptionNumber;\r
-\r
- Status = gRT->SetVariable (\r
- VAR_KEY_ORDER,\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
- KeyOrderSize,\r
- NewKeyOrder\r
- );\r
-\r
- FreePool (KeyOrder);\r
- FreePool (NewKeyOrder);\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
-\r
- Delete Key#### for the given Key Option number.\r
-\r
- @param KeyOptionNumber Key option number for Key####\r
-\r
- @retval EFI_SUCCESS Unregister hotkey successfully.\r
- @retval EFI_NOT_FOUND No Key#### is found for the given Key Option number.\r
-\r
-**/\r
-EFI_STATUS\r
-UnregisterHotkey (\r
- IN UINT16 KeyOptionNumber\r
-)\r
-{\r
- UINT16 KeyOption[10];\r
- UINTN Index;\r
- EFI_STATUS Status;\r
- UINTN Index2Del;\r
- UINT16 *KeyOrder;\r
- UINTN KeyOrderSize;\r
-\r
- //\r
- // Delete variable Key####\r
- //\r
- UnicodeSPrint (KeyOption, sizeof (KeyOption), L"Key%04x", KeyOptionNumber);\r
- gRT->SetVariable (\r
- KeyOption,\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
- 0,\r
- NULL\r
- );\r
-\r
- //\r
- // Adjust key order array\r
- //\r
- KeyOrder = BdsLibGetVariableAndSize (\r
- VAR_KEY_ORDER,\r
- &gEfiGlobalVariableGuid,\r
- &KeyOrderSize\r
- );\r
- if (KeyOrder == NULL) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- Index2Del = 0;\r
- for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index++) {\r
- if (KeyOrder[Index] == KeyOptionNumber) {\r
- Index2Del = Index;\r
- break;\r
- }\r
- }\r
-\r
- if (Index != KeyOrderSize / sizeof (UINT16)) {\r
- //\r
- // KeyOptionNumber found in "KeyOrder", delete it\r
- //\r
- for (Index = Index2Del; Index < KeyOrderSize / sizeof (UINT16) - 1; Index++) {\r
- KeyOrder[Index] = KeyOrder[Index + 1];\r
- }\r
-\r
- KeyOrderSize -= sizeof (UINT16);\r
- }\r
-\r
- Status = gRT->SetVariable (\r
- VAR_KEY_ORDER,\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
- KeyOrderSize,\r
- KeyOrder\r
- );\r
-\r
- FreePool (KeyOrder);\r
-\r
- return Status;\r
-}\r
-\r