]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPkg/Library/BdsLib/BdsLoadOption.c
ARM Packages: Fixed line endings
[mirror_edk2.git] / ArmPkg / Library / BdsLib / BdsLoadOption.c
index 8abbc9b5cd0498916b2b1d1f7b71595a185de679..3f4566ffab133e06396d896213274e2d5bd89ad6 100644 (file)
-/** @file
-*
-*  Copyright (c) 2011-2012, ARM Limited. All rights reserved.
-*
-*  This program and the accompanying materials
-*  are licensed and made available under the terms and conditions of the BSD License
-*  which accompanies this distribution.  The full text of the license may be found at
-*  http://opensource.org/licenses/bsd-license.php
-*
-*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-*
-**/
-
-#include "BdsInternal.h"
-
-EFI_STATUS
-BootOptionParseLoadOption (
-  IN     EFI_LOAD_OPTION EfiLoadOption,
-  IN     UINTN           EfiLoadOptionSize,
-  IN OUT BDS_LOAD_OPTION **BdsLoadOption
-  )
-{
-  BDS_LOAD_OPTION *LoadOption;
-  UINTN           DescriptionLength;
-
-  if (EfiLoadOption == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if (EfiLoadOptionSize < sizeof(UINT32) + sizeof(UINT16) + sizeof(CHAR16) + sizeof(EFI_DEVICE_PATH_PROTOCOL)) {
-    return EFI_BAD_BUFFER_SIZE;
-  }
-
-  if (*BdsLoadOption == NULL) {
-    LoadOption = (BDS_LOAD_OPTION*)AllocateZeroPool (sizeof(BDS_LOAD_OPTION));
-    if (LoadOption == NULL) {
-      return EFI_OUT_OF_RESOURCES;
-    }
-  } else {
-    LoadOption = *BdsLoadOption;
-  }
-
-  LoadOption->LoadOption     = EfiLoadOption;
-  LoadOption->LoadOptionSize = EfiLoadOptionSize;
-
-  LoadOption->Attributes         = *(UINT32*)EfiLoadOption;
-  LoadOption->FilePathListLength = *(UINT16*)(EfiLoadOption + sizeof(UINT32));
-  LoadOption->Description        = (CHAR16*)(EfiLoadOption + sizeof(UINT32) + sizeof(UINT16));
-  DescriptionLength              = StrSize (LoadOption->Description);
-  LoadOption->FilePathList       = (EFI_DEVICE_PATH_PROTOCOL*)(EfiLoadOption + sizeof(UINT32) + sizeof(UINT16) + DescriptionLength);
-
-  // If ((End of EfiLoadOptiony - Start of EfiLoadOption) == EfiLoadOptionSize) then No Optional Data
-  if ((UINTN)((UINTN)LoadOption->FilePathList + LoadOption->FilePathListLength - (UINTN)EfiLoadOption) == EfiLoadOptionSize) {
-    LoadOption->OptionalData     = NULL;
-    LoadOption->OptionalDataSize = 0;
-  } else {
-    LoadOption->OptionalData     = (VOID*)((UINTN)(LoadOption->FilePathList) + LoadOption->FilePathListLength);
-    LoadOption->OptionalDataSize = EfiLoadOptionSize - ((UINTN)LoadOption->OptionalData - (UINTN)EfiLoadOption);
-  }
-
-  if (*BdsLoadOption == NULL) {
-    *BdsLoadOption = LoadOption;
-  }
-
-  return EFI_SUCCESS;
-}
-
-EFI_STATUS
-BootOptionFromLoadOptionVariable (
-  IN  CHAR16*           BootVariableName,
-  OUT BDS_LOAD_OPTION** BdsLoadOption
-  )
-{
-  EFI_STATUS            Status;
-  EFI_LOAD_OPTION       EfiLoadOption;
-  UINTN                 EfiLoadOptionSize;
-
-  Status = GetEnvironmentVariable (BootVariableName, NULL, &EfiLoadOptionSize, (VOID**)&EfiLoadOption);
-  if (!EFI_ERROR(Status)) {
-    *BdsLoadOption = NULL;
-    Status = BootOptionParseLoadOption (EfiLoadOption, EfiLoadOptionSize, BdsLoadOption);
-  }
-
-  return Status;
-}
-
-EFI_STATUS
-BootOptionFromLoadOptionIndex (
-  IN  UINT16            LoadOptionIndex,
-  OUT BDS_LOAD_OPTION **BdsLoadOption
-  )
-{
-  CHAR16        BootVariableName[9];
-  EFI_STATUS    Status;
-
-  UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", LoadOptionIndex);
-
-  Status = BootOptionFromLoadOptionVariable (BootVariableName, BdsLoadOption);
-  if (!EFI_ERROR(Status)) {
-    (*BdsLoadOption)->LoadOptionIndex = LoadOptionIndex;
-  }
-
-  return Status;
-}
-
-EFI_STATUS
-BootOptionToLoadOptionVariable (
-  IN BDS_LOAD_OPTION*   BdsLoadOption
-  )
-{
-  EFI_STATUS                    Status;
-  UINTN                         DescriptionSize;
-  //UINT16                        FilePathListLength;
-  EFI_DEVICE_PATH_PROTOCOL*     DevicePathNode;
-  UINTN                         NodeLength;
-  UINT8*                        EfiLoadOptionPtr;
-  VOID*                         OldLoadOption;
-  CHAR16                        BootVariableName[9];
-  UINTN                         BootOrderSize;
-  UINT16*                       BootOrder;
-
-  // If we are overwriting an existent Boot Option then we have to free previously allocated memory
-  if (BdsLoadOption->LoadOptionSize > 0) {
-    OldLoadOption = BdsLoadOption->LoadOption;
-  } else {
-    OldLoadOption = NULL;
-
-    // If this function is called at the creation of the Boot Device entry (not at the update) the
-    // BootOption->LoadOptionSize must be zero then we get a new BootIndex for this entry
-    BdsLoadOption->LoadOptionIndex = BootOptionAllocateBootIndex ();
-
-    //TODO: Add to the the Boot Entry List
-  }
-
-  DescriptionSize = StrSize(BdsLoadOption->Description);
-
-  // Ensure the FilePathListLength information is correct
-  ASSERT (GetDevicePathSize (BdsLoadOption->FilePathList) == BdsLoadOption->FilePathListLength);
-
-  // Allocate the memory for the EFI Load Option
-  BdsLoadOption->LoadOptionSize = sizeof(UINT32) + sizeof(UINT16) + DescriptionSize + BdsLoadOption->FilePathListLength + BdsLoadOption->OptionalDataSize;
-
-  BdsLoadOption->LoadOption = (EFI_LOAD_OPTION)AllocateZeroPool (BdsLoadOption->LoadOptionSize);
-  if (BdsLoadOption->LoadOption == NULL) {
-    return EFI_OUT_OF_RESOURCES;
-  }
-
-  EfiLoadOptionPtr = BdsLoadOption->LoadOption;
-
-  //
-  // Populate the EFI Load Option and BDS Boot Option structures
-  //
-
-  // Attributes fields
-  *(UINT32*)EfiLoadOptionPtr = BdsLoadOption->Attributes;
-  EfiLoadOptionPtr += sizeof(UINT32);
-
-  // FilePath List fields
-  *(UINT16*)EfiLoadOptionPtr = BdsLoadOption->FilePathListLength;
-  EfiLoadOptionPtr += sizeof(UINT16);
-
-  // Boot description fields
-  CopyMem (EfiLoadOptionPtr, BdsLoadOption->Description, DescriptionSize);
-  EfiLoadOptionPtr += DescriptionSize;
-
-  // File path fields
-  DevicePathNode = BdsLoadOption->FilePathList;
-  while (!IsDevicePathEndType (DevicePathNode)) {
-    NodeLength = DevicePathNodeLength(DevicePathNode);
-    CopyMem (EfiLoadOptionPtr, DevicePathNode, NodeLength);
-    EfiLoadOptionPtr += NodeLength;
-    DevicePathNode = NextDevicePathNode (DevicePathNode);
-  }
-
-  // Set the End Device Path Type
-  SetDevicePathEndNode (EfiLoadOptionPtr);
-  EfiLoadOptionPtr += sizeof(EFI_DEVICE_PATH);
-
-  // Fill the Optional Data
-  if (BdsLoadOption->OptionalDataSize > 0) {
-    CopyMem (EfiLoadOptionPtr, BdsLoadOption->OptionalData, BdsLoadOption->OptionalDataSize);
-  }
-
-  // Case where the fields have been updated
-  if (OldLoadOption) {
-    // Now, the old data has been copied to the new allocated packed structure, we need to update the pointers of BdsLoadOption
-    BootOptionParseLoadOption (BdsLoadOption->LoadOption, BdsLoadOption->LoadOptionSize, &BdsLoadOption);
-    // Free the old packed structure
-    FreePool (OldLoadOption);
-  }
-
-  // Create/Update Boot#### environment variable
-  UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BdsLoadOption->LoadOptionIndex);
-  Status = gRT->SetVariable (
-      BootVariableName,
-      &gEfiGlobalVariableGuid,
-      EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
-      BdsLoadOption->LoadOptionSize,
-      BdsLoadOption->LoadOption
-      );
-
-  // When it is a new entry we must add the entry to the BootOrder
-  if (OldLoadOption == NULL) {
-    // Add the new Boot Index to the list
-    Status = GetEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);
-    if (!EFI_ERROR(Status)) {
-      BootOrder = ReallocatePool (BootOrderSize, BootOrderSize + sizeof(UINT16), BootOrder);
-      // Add the new index at the end
-      BootOrder[BootOrderSize / sizeof(UINT16)] = BdsLoadOption->LoadOptionIndex;
-      BootOrderSize += sizeof(UINT16);
-    } else {
-      // BootOrder does not exist. Create it
-      BootOrderSize = sizeof(UINT16);
-      BootOrder = &(BdsLoadOption->LoadOptionIndex);
-    }
-
-    // Update (or Create) the BootOrder environment variable
-    gRT->SetVariable (
-        L"BootOrder",
-        &gEfiGlobalVariableGuid,
-        EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
-        BootOrderSize,
-        BootOrder
-        );
-    DEBUG((EFI_D_ERROR,"Create %s\n",BootVariableName));
-
-    // Free memory allocated by GetEnvironmentVariable
-    if (!EFI_ERROR(Status)) {
-      FreePool (BootOrder);
-    }
-  } else {
-    DEBUG((EFI_D_ERROR,"Update %s\n",BootVariableName));
-  }
-
-  return EFI_SUCCESS;
-}
-
-UINT16
-BootOptionAllocateBootIndex (
-  VOID
-  )
-{
-  EFI_STATUS        Status;
-  UINTN             Index;
-  UINT32            BootIndex;
-  UINT16            *BootOrder;
-  UINTN             BootOrderSize;
-  BOOLEAN           Found;
-
-  // Get the Boot Option Order from the environment variable
-  Status = GetEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);
-  if (!EFI_ERROR(Status)) {
-    for (BootIndex = 0; BootIndex <= 0xFFFF; BootIndex++) {
-      Found = FALSE;
-      for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {
-        if (BootOrder[Index] == BootIndex) {
-          Found = TRUE;
-          break;
-        }
-      }
-      if (!Found) {
-        return BootIndex;
-      }
-    }
-    FreePool (BootOrder);
-  }
-  // Return the first index
-  return 0;
-}
+/** @file\r
+*\r
+*  Copyright (c) 2011-2012, ARM Limited. All rights reserved.\r
+*\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
+*  http://opensource.org/licenses/bsd-license.php\r
+*\r
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+*\r
+**/\r
+\r
+#include "BdsInternal.h"\r
+\r
+EFI_STATUS\r
+BootOptionParseLoadOption (\r
+  IN     EFI_LOAD_OPTION EfiLoadOption,\r
+  IN     UINTN           EfiLoadOptionSize,\r
+  IN OUT BDS_LOAD_OPTION **BdsLoadOption\r
+  )\r
+{\r
+  BDS_LOAD_OPTION *LoadOption;\r
+  UINTN           DescriptionLength;\r
+\r
+  if (EfiLoadOption == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (EfiLoadOptionSize < sizeof(UINT32) + sizeof(UINT16) + sizeof(CHAR16) + sizeof(EFI_DEVICE_PATH_PROTOCOL)) {\r
+    return EFI_BAD_BUFFER_SIZE;\r
+  }\r
+\r
+  if (*BdsLoadOption == NULL) {\r
+    LoadOption = (BDS_LOAD_OPTION*)AllocateZeroPool (sizeof(BDS_LOAD_OPTION));\r
+    if (LoadOption == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+  } else {\r
+    LoadOption = *BdsLoadOption;\r
+  }\r
+\r
+  LoadOption->LoadOption     = EfiLoadOption;\r
+  LoadOption->LoadOptionSize = EfiLoadOptionSize;\r
+\r
+  LoadOption->Attributes         = *(UINT32*)EfiLoadOption;\r
+  LoadOption->FilePathListLength = *(UINT16*)(EfiLoadOption + sizeof(UINT32));\r
+  LoadOption->Description        = (CHAR16*)(EfiLoadOption + sizeof(UINT32) + sizeof(UINT16));\r
+  DescriptionLength              = StrSize (LoadOption->Description);\r
+  LoadOption->FilePathList       = (EFI_DEVICE_PATH_PROTOCOL*)(EfiLoadOption + sizeof(UINT32) + sizeof(UINT16) + DescriptionLength);\r
+\r
+  // If ((End of EfiLoadOptiony - Start of EfiLoadOption) == EfiLoadOptionSize) then No Optional Data\r
+  if ((UINTN)((UINTN)LoadOption->FilePathList + LoadOption->FilePathListLength - (UINTN)EfiLoadOption) == EfiLoadOptionSize) {\r
+    LoadOption->OptionalData     = NULL;\r
+    LoadOption->OptionalDataSize = 0;\r
+  } else {\r
+    LoadOption->OptionalData     = (VOID*)((UINTN)(LoadOption->FilePathList) + LoadOption->FilePathListLength);\r
+    LoadOption->OptionalDataSize = EfiLoadOptionSize - ((UINTN)LoadOption->OptionalData - (UINTN)EfiLoadOption);\r
+  }\r
+\r
+  if (*BdsLoadOption == NULL) {\r
+    *BdsLoadOption = LoadOption;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+BootOptionFromLoadOptionVariable (\r
+  IN  CHAR16*           BootVariableName,\r
+  OUT BDS_LOAD_OPTION** BdsLoadOption\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  EFI_LOAD_OPTION       EfiLoadOption;\r
+  UINTN                 EfiLoadOptionSize;\r
+\r
+  Status = GetEnvironmentVariable (BootVariableName, NULL, &EfiLoadOptionSize, (VOID**)&EfiLoadOption);\r
+  if (!EFI_ERROR(Status)) {\r
+    *BdsLoadOption = NULL;\r
+    Status = BootOptionParseLoadOption (EfiLoadOption, EfiLoadOptionSize, BdsLoadOption);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+BootOptionFromLoadOptionIndex (\r
+  IN  UINT16            LoadOptionIndex,\r
+  OUT BDS_LOAD_OPTION **BdsLoadOption\r
+  )\r
+{\r
+  CHAR16        BootVariableName[9];\r
+  EFI_STATUS    Status;\r
+\r
+  UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", LoadOptionIndex);\r
+\r
+  Status = BootOptionFromLoadOptionVariable (BootVariableName, BdsLoadOption);\r
+  if (!EFI_ERROR(Status)) {\r
+    (*BdsLoadOption)->LoadOptionIndex = LoadOptionIndex;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+BootOptionToLoadOptionVariable (\r
+  IN BDS_LOAD_OPTION*   BdsLoadOption\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  UINTN                         DescriptionSize;\r
+  //UINT16                        FilePathListLength;\r
+  EFI_DEVICE_PATH_PROTOCOL*     DevicePathNode;\r
+  UINTN                         NodeLength;\r
+  UINT8*                        EfiLoadOptionPtr;\r
+  VOID*                         OldLoadOption;\r
+  CHAR16                        BootVariableName[9];\r
+  UINTN                         BootOrderSize;\r
+  UINT16*                       BootOrder;\r
+\r
+  // If we are overwriting an existent Boot Option then we have to free previously allocated memory\r
+  if (BdsLoadOption->LoadOptionSize > 0) {\r
+    OldLoadOption = BdsLoadOption->LoadOption;\r
+  } else {\r
+    OldLoadOption = NULL;\r
+\r
+    // If this function is called at the creation of the Boot Device entry (not at the update) the\r
+    // BootOption->LoadOptionSize must be zero then we get a new BootIndex for this entry\r
+    BdsLoadOption->LoadOptionIndex = BootOptionAllocateBootIndex ();\r
+\r
+    //TODO: Add to the the Boot Entry List\r
+  }\r
+\r
+  DescriptionSize = StrSize(BdsLoadOption->Description);\r
+\r
+  // Ensure the FilePathListLength information is correct\r
+  ASSERT (GetDevicePathSize (BdsLoadOption->FilePathList) == BdsLoadOption->FilePathListLength);\r
+\r
+  // Allocate the memory for the EFI Load Option\r
+  BdsLoadOption->LoadOptionSize = sizeof(UINT32) + sizeof(UINT16) + DescriptionSize + BdsLoadOption->FilePathListLength + BdsLoadOption->OptionalDataSize;\r
+\r
+  BdsLoadOption->LoadOption = (EFI_LOAD_OPTION)AllocateZeroPool (BdsLoadOption->LoadOptionSize);\r
+  if (BdsLoadOption->LoadOption == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  EfiLoadOptionPtr = BdsLoadOption->LoadOption;\r
+\r
+  //\r
+  // Populate the EFI Load Option and BDS Boot Option structures\r
+  //\r
+\r
+  // Attributes fields\r
+  *(UINT32*)EfiLoadOptionPtr = BdsLoadOption->Attributes;\r
+  EfiLoadOptionPtr += sizeof(UINT32);\r
+\r
+  // FilePath List fields\r
+  *(UINT16*)EfiLoadOptionPtr = BdsLoadOption->FilePathListLength;\r
+  EfiLoadOptionPtr += sizeof(UINT16);\r
+\r
+  // Boot description fields\r
+  CopyMem (EfiLoadOptionPtr, BdsLoadOption->Description, DescriptionSize);\r
+  EfiLoadOptionPtr += DescriptionSize;\r
+\r
+  // File path fields\r
+  DevicePathNode = BdsLoadOption->FilePathList;\r
+  while (!IsDevicePathEndType (DevicePathNode)) {\r
+    NodeLength = DevicePathNodeLength(DevicePathNode);\r
+    CopyMem (EfiLoadOptionPtr, DevicePathNode, NodeLength);\r
+    EfiLoadOptionPtr += NodeLength;\r
+    DevicePathNode = NextDevicePathNode (DevicePathNode);\r
+  }\r
+\r
+  // Set the End Device Path Type\r
+  SetDevicePathEndNode (EfiLoadOptionPtr);\r
+  EfiLoadOptionPtr += sizeof(EFI_DEVICE_PATH);\r
+\r
+  // Fill the Optional Data\r
+  if (BdsLoadOption->OptionalDataSize > 0) {\r
+    CopyMem (EfiLoadOptionPtr, BdsLoadOption->OptionalData, BdsLoadOption->OptionalDataSize);\r
+  }\r
+\r
+  // Case where the fields have been updated\r
+  if (OldLoadOption) {\r
+    // Now, the old data has been copied to the new allocated packed structure, we need to update the pointers of BdsLoadOption\r
+    BootOptionParseLoadOption (BdsLoadOption->LoadOption, BdsLoadOption->LoadOptionSize, &BdsLoadOption);\r
+    // Free the old packed structure\r
+    FreePool (OldLoadOption);\r
+  }\r
+\r
+  // Create/Update Boot#### environment variable\r
+  UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BdsLoadOption->LoadOptionIndex);\r
+  Status = gRT->SetVariable (\r
+      BootVariableName,\r
+      &gEfiGlobalVariableGuid,\r
+      EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+      BdsLoadOption->LoadOptionSize,\r
+      BdsLoadOption->LoadOption\r
+      );\r
+\r
+  // When it is a new entry we must add the entry to the BootOrder\r
+  if (OldLoadOption == NULL) {\r
+    // Add the new Boot Index to the list\r
+    Status = GetEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);\r
+    if (!EFI_ERROR(Status)) {\r
+      BootOrder = ReallocatePool (BootOrderSize, BootOrderSize + sizeof(UINT16), BootOrder);\r
+      // Add the new index at the end\r
+      BootOrder[BootOrderSize / sizeof(UINT16)] = BdsLoadOption->LoadOptionIndex;\r
+      BootOrderSize += sizeof(UINT16);\r
+    } else {\r
+      // BootOrder does not exist. Create it\r
+      BootOrderSize = sizeof(UINT16);\r
+      BootOrder = &(BdsLoadOption->LoadOptionIndex);\r
+    }\r
+\r
+    // Update (or Create) the BootOrder environment variable\r
+    gRT->SetVariable (\r
+        L"BootOrder",\r
+        &gEfiGlobalVariableGuid,\r
+        EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+        BootOrderSize,\r
+        BootOrder\r
+        );\r
+    DEBUG((EFI_D_ERROR,"Create %s\n",BootVariableName));\r
+\r
+    // Free memory allocated by GetEnvironmentVariable\r
+    if (!EFI_ERROR(Status)) {\r
+      FreePool (BootOrder);\r
+    }\r
+  } else {\r
+    DEBUG((EFI_D_ERROR,"Update %s\n",BootVariableName));\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+UINT16\r
+BootOptionAllocateBootIndex (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS        Status;\r
+  UINTN             Index;\r
+  UINT32            BootIndex;\r
+  UINT16            *BootOrder;\r
+  UINTN             BootOrderSize;\r
+  BOOLEAN           Found;\r
+\r
+  // Get the Boot Option Order from the environment variable\r
+  Status = GetEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);\r
+  if (!EFI_ERROR(Status)) {\r
+    for (BootIndex = 0; BootIndex <= 0xFFFF; BootIndex++) {\r
+      Found = FALSE;\r
+      for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {\r
+        if (BootOrder[Index] == BootIndex) {\r
+          Found = TRUE;\r
+          break;\r
+        }\r
+      }\r
+      if (!Found) {\r
+        return BootIndex;\r
+      }\r
+    }\r
+    FreePool (BootOrder);\r
+  }\r
+  // Return the first index\r
+  return 0;\r
+}\r