return (BOOLEAN) ((KeyOption->BootOptionCrc == Crc) ? TRUE : FALSE);\r
}\r
\r
-/**\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) + KEY_OPTION_INPUT_KEY_COUNT (KeyOption) * 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 == TempOption->KeyData) {\r
- if (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
/**\r
Try to boot the boot option triggered by hotkey.\r
@retval EFI_SUCCESS There is HotkeyBootOption & it is processed\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Return TRUE when the variable pointed by Name and Guid is a Key#### variable.\r
+\r
+ @param Name The name of the variable.\r
+ @param Guid The GUID of the variable.\r
+ @param OptionNumber Return the option number parsed from the Name.\r
+\r
+ @retval TRUE The variable pointed by Name and Guid is a Key#### variable.\r
+ @retval FALSE The variable pointed by Name and Guid isn't a Key#### variable.\r
+**/\r
+BOOLEAN\r
+IsKeyOptionVariable (\r
+ CHAR16 *Name,\r
+ EFI_GUID *Guid,\r
+ UINT16 *OptionNumber\r
+ )\r
+{\r
+ UINTN Index;\r
+ \r
+ if (!CompareGuid (Guid, &gEfiGlobalVariableGuid) ||\r
+ (StrSize (Name) != sizeof (L"Key####")) ||\r
+ (StrnCmp (Name, L"Key", 3) != 0)\r
+ ) {\r
+ return FALSE;\r
+ }\r
+\r
+ *OptionNumber = 0;\r
+ for (Index = 3; Index < 7; Index++) {\r
+ if ((Name[Index] >= L'0') && (Name[Index] <= L'9')) {\r
+ *OptionNumber = *OptionNumber * 10 + Name[Index] - L'0';\r
+ } else if ((Name[Index] >= L'A') && (Name[Index] <= L'F')) {\r
+ *OptionNumber = *OptionNumber * 10 + Name[Index] - L'A';\r
+ } else {\r
+ return FALSE;\r
+ }\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Return an array of key option numbers.\r
+\r
+ @param Count Return the count of key option numbers.\r
+\r
+ @return UINT16* Pointer to an array of key option numbers;\r
+**/\r
+UINT16 *\r
+EFIAPI\r
+HotkeyGetOptionNumbers (\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
+ UINT16 *OptionNumbers;\r
+ UINT16 OptionNumber;\r
+\r
+ if (Count == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ *Count = 0;\r
+ OptionNumbers = 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 (IsKeyOptionVariable (Name ,&Guid, &OptionNumber)) {\r
+ OptionNumbers = ReallocatePool (\r
+ *Count * sizeof (UINT16),\r
+ (*Count + 1) * sizeof (UINT16),\r
+ OptionNumbers\r
+ );\r
+ ASSERT (OptionNumbers != NULL);\r
+ for (Index = 0; Index < *Count; Index++) {\r
+ if (OptionNumber < OptionNumbers[Index]) {\r
+ break;\r
+ }\r
+ }\r
+ CopyMem (&OptionNumbers[Index + 1], &OptionNumbers[Index], (*Count - Index) * sizeof (UINT16));\r
+ OptionNumbers[Index] = OptionNumber;\r
+ (*Count)++;\r
+ }\r
+ }\r
+\r
+ FreePool (Name);\r
+\r
+ return OptionNumbers;\r
+}\r
+\r
/**\r
\r
Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options.\r
\r
@retval EFI_SUCCESS Hotkey services successfully initialized.\r
- @retval EFI_NOT_FOUND Can not find the "KeyOrder" variable\r
**/\r
EFI_STATUS\r
InitializeHotkeyService (\r
{\r
EFI_STATUS Status;\r
UINT32 BootOptionSupport;\r
- UINT16 *KeyOrder;\r
- UINTN KeyOrderSize;\r
+ UINT16 *KeyOptionNumbers;\r
+ UINTN KeyOptionCount;\r
UINTN Index;\r
- UINT16 KeyOptionName[8];\r
- UINTN KeyOptionSize;\r
+ CHAR16 KeyOptionName[8];\r
EFI_KEY_OPTION *KeyOption;\r
\r
//\r
sizeof (UINT32),\r
&BootOptionSupport\r
);\r
+ ASSERT_EFI_ERROR (Status);\r
\r
- //\r
- // Get valid Key Option List from private EFI variable "KeyOrder"\r
- //\r
- KeyOrder = BdsLibGetVariableAndSize (\r
- VAR_KEY_ORDER,\r
- &gEfiGlobalVariableGuid,\r
- &KeyOrderSize\r
- );\r
-\r
- if (KeyOrder == NULL) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index ++) {\r
- UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOrder[Index]);\r
- KeyOption = BdsLibGetVariableAndSize (\r
- KeyOptionName,\r
- &gEfiGlobalVariableGuid,\r
- &KeyOptionSize\r
- );\r
-\r
- if (KeyOption == NULL || !IsKeyOptionValid (KeyOption)) {\r
- UnregisterHotkey (KeyOrder[Index]);\r
- } else {\r
+ KeyOptionNumbers = HotkeyGetOptionNumbers (&KeyOptionCount);\r
+ for (Index = 0; Index < KeyOptionCount; Index ++) {\r
+ UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOptionNumbers[Index]);\r
+ GetEfiGlobalVariable2 (KeyOptionName, (VOID **) &KeyOption, NULL);\r
+ ASSERT (KeyOption != NULL);\r
+ if (IsKeyOptionValid (KeyOption)) {\r
HotkeyInsertList (KeyOption);\r
}\r
+ FreePool (KeyOption);\r
+ }\r
+\r
+ if (KeyOptionNumbers != NULL) {\r
+ FreePool (KeyOptionNumbers);\r
}\r
\r
//\r