Provides a way for 3rd party applications to register themselves for launch by the\r
Boot Manager based on hot key\r
\r
-Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2007 - 2012, 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
}\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
+ Try to boot the boot option triggered by hotkey.\r
+ @retval EFI_SUCCESS There is HotkeyBootOption & it is processed\r
+ @retval EFI_NOT_FOUND There is no HotkeyBootOption\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
+HotkeyBoot (\r
+ VOID\r
+ )\r
+{ \r
+ EFI_STATUS Status;\r
+ UINTN ExitDataSize;\r
+ CHAR16 *ExitData;\r
\r
- KeyOptionSize = sizeof (EFI_KEY_OPTION) + KeyOption->KeyData.Options.InputKeyCount * sizeof (EFI_INPUT_KEY);\r
- UpdateBootOption = FALSE;\r
+ if (mHotkeyBootOption == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ } \r
+ \r
+ BdsLibConnectDevicePath (mHotkeyBootOption->DevicePath);\r
\r
//\r
- // Check whether HotKey conflict with keys used by Setup Browser\r
+ // Clear the screen before launch this BootOption\r
//\r
- KeyOrder = BdsLibGetVariableAndSize (\r
- VAR_KEY_ORDER,\r
- &gEfiGlobalVariableGuid,\r
- &KeyOrderSize\r
- );\r
- if (KeyOrder == NULL) {\r
- KeyOrderSize = 0;\r
- }\r
+ gST->ConOut->Reset (gST->ConOut, FALSE);\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
+ Status = BdsLibBootViaBootOption (mHotkeyBootOption, mHotkeyBootOption->DevicePath, &ExitDataSize, &ExitData);\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
+ // Call platform action to indicate the boot fail\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
-**/\r
-VOID\r
-HotkeyBoot (\r
- VOID\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN ExitDataSize;\r
- CHAR16 *ExitData;\r
- \r
- if (mHotkeyBootOption != NULL) {\r
- BdsLibConnectDevicePath (mHotkeyBootOption->DevicePath);\r
-\r
+ mHotkeyBootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));\r
+ PlatformBdsBootFail (mHotkeyBootOption, Status, ExitData, ExitDataSize);\r
+ } else {\r
//\r
- // Clear the screen before launch this BootOption\r
+ // Call platform action to indicate the boot success\r
//\r
- gST->ConOut->Reset (gST->ConOut, FALSE);\r
-\r
- Status = BdsLibBootViaBootOption (mHotkeyBootOption, mHotkeyBootOption->DevicePath, &ExitDataSize, &ExitData);\r
+ mHotkeyBootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));\r
+ PlatformBdsBootSuccess (mHotkeyBootOption);\r
+ }\r
+ FreePool (mHotkeyBootOption->Description);\r
+ FreePool (mHotkeyBootOption->DevicePath);\r
+ FreePool (mHotkeyBootOption->LoadOptions);\r
+ FreePool (mHotkeyBootOption);\r
\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Call platform action to indicate the boot fail\r
- //\r
- mHotkeyBootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));\r
- PlatformBdsBootFail (mHotkeyBootOption, Status, ExitData, ExitDataSize);\r
- } else {\r
- //\r
- // Call platform action to indicate the boot success\r
- //\r
- mHotkeyBootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));\r
- PlatformBdsBootSuccess (mHotkeyBootOption);\r
- }\r
- FreePool (mHotkeyBootOption->Description);\r
- FreePool (mHotkeyBootOption->DevicePath);\r
- FreePool (mHotkeyBootOption->LoadOptions);\r
- FreePool (mHotkeyBootOption);\r
+ mHotkeyBootOption = NULL;\r
\r
- mHotkeyBootOption = NULL;\r
- }\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\r
BDS_HOTKEY_OPTION *HotkeyLeft;\r
BDS_HOTKEY_OPTION *HotkeyRight;\r
UINTN Index;\r
- EFI_BOOT_KEY_DATA KeyOptions;\r
UINT32 KeyShiftStateLeft;\r
UINT32 KeyShiftStateRight;\r
EFI_INPUT_KEY *InputKey;\r
\r
HotkeyLeft->Signature = BDS_HOTKEY_OPTION_SIGNATURE;\r
HotkeyLeft->BootOptionNumber = KeyOption->BootOption;\r
-\r
- KeyOptions = KeyOption->KeyData;\r
-\r
- HotkeyLeft->CodeCount = (UINT8) KeyOptions.Options.InputKeyCount;\r
+ HotkeyLeft->CodeCount = (UINT8) KEY_OPTION_INPUT_KEY_COUNT (KeyOption);\r
\r
//\r
// Map key shift state from KeyOptions to EFI_KEY_DATA.KeyState\r
//\r
KeyShiftStateRight = EFI_SHIFT_STATE_VALID;\r
- if (KeyOptions.Options.ShiftPressed) {\r
+ if (KEY_OPTION_SHIFT_PRESSED (KeyOption)) {\r
KeyShiftStateRight |= EFI_RIGHT_SHIFT_PRESSED;\r
}\r
- if (KeyOptions.Options.ControlPressed) {\r
+ if (KEY_OPTION_CONTROL_PRESSED (KeyOption)) {\r
KeyShiftStateRight |= EFI_RIGHT_CONTROL_PRESSED;\r
}\r
- if (KeyOptions.Options.AltPressed) {\r
+ if (KEY_OPTION_ALT_PRESSED (KeyOption)) {\r
KeyShiftStateRight |= EFI_RIGHT_ALT_PRESSED;\r
}\r
- if (KeyOptions.Options.LogoPressed) {\r
+ if (KEY_OPTION_LOGO_PRESSED (KeyOption)) {\r
KeyShiftStateRight |= EFI_RIGHT_LOGO_PRESSED;\r
}\r
- if (KeyOptions.Options.MenuPressed) {\r
+ if (KEY_OPTION_MENU_PRESSED (KeyOption)) {\r
KeyShiftStateRight |= EFI_MENU_KEY_PRESSED;\r
}\r
- if (KeyOptions.Options.SysReqPressed) {\r
+ if (KEY_OPTION_SYS_REQ_PRESSED (KeyOption)) {\r
KeyShiftStateRight |= EFI_SYS_REQ_PRESSED;\r
}\r
\r
-\r
KeyShiftStateLeft = (KeyShiftStateRight & 0xffffff00) | ((KeyShiftStateRight & 0xff) << 1);\r
\r
InputKey = (EFI_INPUT_KEY *) (((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION));\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
- // Export our capability - EFI_BOOT_OPTION_SUPPORT_KEY and EFI_BOOT_OPTION_SUPPORT_APP\r
+ // Export our capability - EFI_BOOT_OPTION_SUPPORT_KEY and EFI_BOOT_OPTION_SUPPORT_APP.\r
// with maximum number of key presses of 3\r
+ // Do not report the hotkey capability if PcdConInConnectOnDemand is enabled.\r
//\r
- BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_KEY | EFI_BOOT_OPTION_SUPPORT_APP;\r
- SET_BOOT_OPTION_SUPPORT_KEY_COUNT (BootOptionSupport, 3);\r
+ BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_APP;\r
+ if (!PcdGetBool (PcdConInConnectOnDemand)) {\r
+ BootOptionSupport |= EFI_BOOT_OPTION_SUPPORT_KEY;\r
+ SET_BOOT_OPTION_SUPPORT_KEY_COUNT (BootOptionSupport, 3);\r
+ }\r
+\r
Status = gRT->SetVariable (\r
L"BootOptionSupport",\r
&gEfiGlobalVariableGuid,\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