]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.c
Add assertion to make sure the pointer is not NULL.
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / BdsDxe / Hotkey.c
index da0a2eef5aa9ff6842acc457c473dacdfc9cb2be..1a3ec1ff844039f000213a09082225a4a68cf6f6 100644 (file)
@@ -2,7 +2,7 @@
   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 - 2010, 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
@@ -16,10 +16,10 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include "Hotkey.h"\r
 \r
 \r
-LIST_ENTRY      mHotkeyList = INITIALIZE_LIST_HEAD_VARIABLE (mHotkeyList);\r
-BOOLEAN         mHotkeyCallbackPending = FALSE;\r
-EFI_EVENT       mHotkeyEvent;\r
-VOID            *mHotkeyRegistration;\r
+LIST_ENTRY        mHotkeyList = INITIALIZE_LIST_HEAD_VARIABLE (mHotkeyList);\r
+BDS_COMMON_OPTION *mHotkeyBootOption = NULL;\r
+EFI_EVENT         mHotkeyEvent;\r
+VOID              *mHotkeyRegistration;\r
 \r
 \r
 /**\r
@@ -65,239 +65,53 @@ IsKeyOptionValid (
 }\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
-\r
-  KeyOptionSize = sizeof (EFI_KEY_OPTION) + KeyOption->KeyData.Options.InputKeyCount * sizeof (EFI_INPUT_KEY);\r
-  UpdateBootOption = FALSE;\r
+HotkeyBoot (\r
+  VOID\r
+  )\r
+{ \r
+  EFI_STATUS           Status;\r
+  UINTN                ExitDataSize;\r
+  CHAR16               *ExitData;\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
+  if (mHotkeyBootOption == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  } \r
+  \r
+  BdsLibConnectDevicePath (mHotkeyBootOption->DevicePath);\r
 \r
   //\r
-  // Find free key option number\r
+  // Clear the screen before launch this BootOption\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
+  gST->ConOut->Reset (gST->ConOut, FALSE);\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
+  Status = BdsLibBootViaBootOption (mHotkeyBootOption, mHotkeyBootOption->DevicePath, &ExitDataSize, &ExitData);\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
+    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
 \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
+  mHotkeyBootOption = NULL;\r
 \r
-  FreePool (KeyOrder);\r
-\r
-  return Status;\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
@@ -322,24 +136,22 @@ HotkeyCallback (
   LIST_ENTRY         *Link;\r
   BDS_HOTKEY_OPTION  *Hotkey;\r
   UINT16             Buffer[10];\r
-  BDS_COMMON_OPTION  *BootOption;\r
-  UINTN              ExitDataSize;\r
-  CHAR16             *ExitData;\r
   EFI_STATUS         Status;\r
   EFI_KEY_DATA       *HotkeyData;\r
 \r
-  if (mHotkeyCallbackPending) {\r
+  if (mHotkeyBootOption != NULL) {\r
     //\r
-    // When responsing to a Hotkey, ignore sequential hotkey stroke until\r
-    // the current Boot#### load option returned\r
+    // Do not process sequential hotkey stroke until the current boot option returns\r
     //\r
     return EFI_SUCCESS;\r
   }\r
 \r
-  Status = EFI_SUCCESS;\r
-  Link = GetFirstNode (&mHotkeyList);\r
+  Status                 = EFI_SUCCESS;\r
 \r
-  while (!IsNull (&mHotkeyList, Link)) {\r
+  for ( Link = GetFirstNode (&mHotkeyList)\r
+      ; !IsNull (&mHotkeyList, Link)\r
+      ; Link = GetNextNode (&mHotkeyList, Link)\r
+      ) {\r
     HotkeyCatched = FALSE;\r
     Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);\r
 \r
@@ -349,26 +161,19 @@ HotkeyCallback (
     ASSERT (Hotkey->WaitingKey < (sizeof (Hotkey->KeyData) / sizeof (Hotkey->KeyData[0])));\r
     HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey];\r
     if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) &&\r
-       (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) &&\r
-       (((HotkeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) ? (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : TRUE)) {\r
+        (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) &&\r
+        (((KeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) ? \r
+          (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : TRUE\r
+        )\r
+       ) {\r
       //\r
-      // Receive an expecting key stroke\r
+      // For hotkey of key combination, transit to next waiting state\r
       //\r
-      if (Hotkey->CodeCount > 1) {\r
-        //\r
-        // For hotkey of key combination, transit to next waiting state\r
-        //\r
-        Hotkey->WaitingKey++;\r
+      Hotkey->WaitingKey++;\r
 \r
-        if (Hotkey->WaitingKey == Hotkey->CodeCount) {\r
-          //\r
-          // Received the whole key stroke sequence\r
-          //\r
-          HotkeyCatched = TRUE;\r
-        }\r
-      } else {\r
+      if (Hotkey->WaitingKey == Hotkey->CodeCount) {\r
         //\r
-        // For hotkey of single key stroke\r
+        // Received the whole key stroke sequence\r
         //\r
         HotkeyCatched = TRUE;\r
       }\r
@@ -391,38 +196,8 @@ HotkeyCallback (
       InitializeListHead (&BootLists);\r
 \r
       UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", Hotkey->BootOptionNumber);\r
-      BootOption = BdsLibVariableToOption (&BootLists, Buffer);\r
-      if (BootOption == NULL) {\r
-        return EFI_NOT_FOUND;\r
-      }\r
-      BootOption->BootCurrent = Hotkey->BootOptionNumber;\r
-      BdsLibConnectDevicePath (BootOption->DevicePath);\r
-\r
-      //\r
-      // Clear the screen before launch this BootOption\r
-      //\r
-      gST->ConOut->Reset (gST->ConOut, FALSE);\r
-\r
-      mHotkeyCallbackPending = TRUE;\r
-      Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);\r
-      mHotkeyCallbackPending = FALSE;\r
-\r
-      if (EFI_ERROR (Status)) {\r
-        //\r
-        // Call platform action to indicate the boot fail\r
-        //\r
-        BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));\r
-        PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);\r
-      } else {\r
-        //\r
-        // Call platform action to indicate the boot success\r
-        //\r
-        BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));\r
-        PlatformBdsBootSuccess (BootOption);\r
-      }\r
+      mHotkeyBootOption = BdsLibVariableToOption (&BootLists, Buffer);\r
     }\r
-\r
-    Link = GetNextNode (&mHotkeyList, Link);\r
   }\r
 \r
   return Status;\r
@@ -540,7 +315,6 @@ HotkeyInsertList (
   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
@@ -553,35 +327,31 @@ HotkeyInsertList (
 \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
@@ -629,12 +399,121 @@ HotkeyInsertList (
   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
@@ -643,19 +522,23 @@ InitializeHotkeyService (
 {\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
@@ -663,33 +546,21 @@ InitializeHotkeyService (
                   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