]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPkg/Application/LinuxLoader/LinuxConfig.c
ARM Packages: Fixed line endings
[mirror_edk2.git] / ArmPkg / Application / LinuxLoader / LinuxConfig.c
index 68f7b32c0a278e780674ec7184d9053036306649..0d0b8b47463318810d9e57bb95769478c810b0e1 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 "LinuxInternal.h"
-
-//TODO: RemoveMe
-#include <Protocol/DevicePathToText.h>
-
-#define DEFAULT_BOOT_ENTRY_DESCRIPTION  L"Linux"
-#define MAX_STR_INPUT                   300
-#define MAX_ASCII_INPUT                 300
-
-typedef enum {
-  LINUX_LOADER_NEW = 1,
-  LINUX_LOADER_UPDATE
-} LINUX_LOADER_ACTION;
-
-STATIC
-EFI_STATUS
-EditHIInputStr (
-  IN OUT CHAR16  *CmdLine,
-  IN     UINTN   MaxCmdLine
-  )
-{
-  UINTN           CmdLineIndex;
-  UINTN           WaitIndex;
-  CHAR8           Char;
-  EFI_INPUT_KEY   Key;
-  EFI_STATUS      Status;
-
-  Print (CmdLine);
-
-  for (CmdLineIndex = StrLen (CmdLine); CmdLineIndex < MaxCmdLine; ) {
-    Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &WaitIndex);
-    ASSERT_EFI_ERROR (Status);
-
-    Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
-    ASSERT_EFI_ERROR (Status);
-
-    // Unicode character is valid when Scancode is NUll
-    if (Key.ScanCode == SCAN_NULL) {
-      // Scan code is NUll, hence read Unicode character
-      Char = (CHAR8)Key.UnicodeChar;
-    } else {
-      Char = CHAR_NULL;
-    }
-
-    if ((Char == CHAR_LINEFEED) || (Char == CHAR_CARRIAGE_RETURN) || (Char == 0x7f)) {
-      CmdLine[CmdLineIndex] = '\0';
-      Print (L"\n\r");
-
-      return EFI_SUCCESS;
-    } else if ((Key.UnicodeChar == L'\b') || (Key.ScanCode == SCAN_LEFT) || (Key.ScanCode == SCAN_DELETE)){
-      if (CmdLineIndex != 0) {
-        CmdLineIndex--;
-        Print (L"\b \b");
-      }
-    } else if ((Key.ScanCode == SCAN_ESC) || (Char == 0x1B) || (Char == 0x0)) {
-      return EFI_INVALID_PARAMETER;
-    } else {
-      CmdLine[CmdLineIndex++] = Key.UnicodeChar;
-      Print (L"%c", Key.UnicodeChar);
-    }
-  }
-
-  return EFI_SUCCESS;
-}
-
-STATIC
-EFI_STATUS
-EditHIInputAscii (
-  IN OUT CHAR8   *CmdLine,
-  IN     UINTN   MaxCmdLine
-  )
-{
-  CHAR16*     Str;
-  EFI_STATUS  Status;
-
-  Str = (CHAR16*)AllocatePool (MaxCmdLine * sizeof(CHAR16));
-  AsciiStrToUnicodeStr (CmdLine, Str);
-
-  Status = EditHIInputStr (Str, MaxCmdLine);
-
-  UnicodeStrToAsciiStr (Str, CmdLine);
-  FreePool (Str);
-
-  return Status;
-}
-
-STATIC
-EFI_STATUS
-GetHIInputInteger (
-  OUT UINTN   *Integer
-  )
-{
-  CHAR16      CmdLine[255];
-  EFI_STATUS  Status;
-
-  CmdLine[0] = '\0';
-  Status = EditHIInputStr (CmdLine, 255);
-  if (!EFI_ERROR(Status)) {
-    *Integer = StrDecimalToUintn (CmdLine);
-  }
-
-  return Status;
-}
-
-#if 0
-EFI_STATUS
-GenerateDeviceDescriptionName (
-  IN  EFI_HANDLE  Handle,
-  IN OUT CHAR16*  Description
-  )
-{
-  EFI_STATUS                        Status;
-  EFI_COMPONENT_NAME_PROTOCOL*      ComponentName2Protocol;
-  EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;
-  EFI_DEVICE_PATH_PROTOCOL*         DevicePathProtocol;
-  CHAR16*                           DriverName;
-  CHAR16*                           DevicePathTxt;
-  EFI_DEVICE_PATH*                  DevicePathNode;
-
-  ComponentName2Protocol = NULL;
-  Status = gBS->HandleProtocol (Handle, &gEfiComponentName2ProtocolGuid, (VOID **)&ComponentName2Protocol);
-  if (!EFI_ERROR(Status)) {
-    //TODO: Fixme. we must find the best langague
-    Status = ComponentName2Protocol->GetDriverName (ComponentName2Protocol,"en",&DriverName);
-    if (!EFI_ERROR(Status)) {
-      StrnCpy (Description,DriverName,BOOT_DEVICE_DESCRIPTION_MAX);
-    }
-  }
-
-  if (EFI_ERROR(Status)) {
-    // Use the lastest non null entry of the Device path as a description
-    Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);
-    if (EFI_ERROR(Status)) {
-      return Status;
-    }
-
-    // Convert the last non end-type Device Path Node in text for the description
-    DevicePathNode = GetLastDevicePathNode (DevicePathProtocol);
-    Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);
-    ASSERT_EFI_ERROR(Status);
-    DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText(DevicePathNode,TRUE,TRUE);
-    StrnCpy (Description, DevicePathTxt, BOOT_DEVICE_DESCRIPTION_MAX);
-    FreePool (DevicePathTxt);
-  }
-
-  return EFI_SUCCESS;
-}
-#endif
-
-EFI_STATUS
-LinuxLoaderConfig (
-  IN EFI_LOADED_IMAGE_PROTOCOL   *LoadedImage
-  )
-{
-  EFI_STATUS                   Status;
-  LINUX_LOADER_ACTION          Choice;
-  UINTN                        BootOrderSize;
-  UINT16*                      BootOrder;
-  UINTN                        BootOrderCount;
-  UINTN                        Index;
-  CHAR16                       Description[MAX_ASCII_INPUT];
-  CHAR8                        CmdLine[MAX_ASCII_INPUT];
-  CHAR16                       Initrd[MAX_STR_INPUT];
-  UINT16                       InitrdPathListLength;
-  UINT16                       CmdLineLength;
-  BDS_LOAD_OPTION*             BdsLoadOption;
-  BDS_LOAD_OPTION**            SupportedBdsLoadOptions;
-  UINTN                        SupportedBdsLoadOptionCount;
-  LINUX_LOADER_OPTIONAL_DATA*  LinuxOptionalData;
-  EFI_DEVICE_PATH*             DevicePathRoot;
-
-  SupportedBdsLoadOptions = NULL;
-  SupportedBdsLoadOptionCount = 0;
-
-  do {
-    Print (L"[%d] Create new Linux Boot Entry\n",LINUX_LOADER_NEW);
-    Print (L"[%d] Update Linux Boot Entry\n",LINUX_LOADER_UPDATE);
-
-    Print (L"Option: ");
-    Status = GetHIInputInteger (&Choice);
-    if (Status == EFI_INVALID_PARAMETER) {
-      Print (L"\n");
-      return Status;
-    } else if ((Choice != LINUX_LOADER_NEW) && (Choice != LINUX_LOADER_UPDATE)) {
-      Print (L"Error: the option should be either '%d' or '%d'\n",LINUX_LOADER_NEW,LINUX_LOADER_UPDATE);
-      Status = EFI_INVALID_PARAMETER;
-    }
-  } while (EFI_ERROR(Status));
-
-  if (Choice == LINUX_LOADER_UPDATE) {
-    // If no compatible entry then we just create a new entry
-    Choice = LINUX_LOADER_NEW;
-
-    // Scan the OptionalData of every entry for the correct signature
-    Status = GetEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);
-    if (!EFI_ERROR(Status)) {
-      BootOrderCount = BootOrderSize / sizeof(UINT16);
-
-      // Allocate an array to handle maximum number of supported Boot Entry
-      SupportedBdsLoadOptions = (BDS_LOAD_OPTION**)AllocatePool(sizeof(BDS_LOAD_OPTION*) * BootOrderCount);
-
-      SupportedBdsLoadOptionCount = 0;
-
-      // Check if the signature is present in the list of the current Boot entries
-      for (Index = 0; Index < BootOrderCount; Index++) {
-        Status = BootOptionFromLoadOptionIndex (BootOrder[Index], &BdsLoadOption);
-        if (!EFI_ERROR(Status)) {
-          if ((BdsLoadOption->OptionalDataSize >= sizeof(UINT32)) &&
-              (*(UINT32*)BdsLoadOption->OptionalData == LINUX_LOADER_SIGNATURE)) {
-            SupportedBdsLoadOptions[SupportedBdsLoadOptionCount++] = BdsLoadOption;
-            Choice = LINUX_LOADER_UPDATE;
-          }
-        }
-      }
-    }
-    FreePool (BootOrder);
-  }
-
-  if (Choice == LINUX_LOADER_NEW) {
-    Description[0] = '\0';
-    CmdLine[0]     = '\0';
-    Initrd[0]      = '\0';
-
-    BdsLoadOption = (BDS_LOAD_OPTION*)AllocateZeroPool (sizeof(BDS_LOAD_OPTION));
-
-    DEBUG_CODE_BEGIN();
-      CHAR16*                           DevicePathTxt;
-      EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;
-
-      Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);
-      ASSERT_EFI_ERROR(Status);
-      DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (LoadedImage->FilePath, TRUE, TRUE);
-
-      Print(L"EFI OS Loader: %s\n",DevicePathTxt);
-
-      FreePool(DevicePathTxt);
-    DEBUG_CODE_END();
-
-    //
-    // Fill the known fields of BdsLoadOption
-    //
-
-    BdsLoadOption->Attributes = LOAD_OPTION_ACTIVE | LOAD_OPTION_CATEGORY_BOOT;
-
-    // Get the full Device Path for this file
-    Status = gBS->HandleProtocol (LoadedImage->DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathRoot);
-    ASSERT_EFI_ERROR(Status);
-
-    BdsLoadOption->FilePathList = AppendDevicePath (DevicePathRoot, LoadedImage->FilePath);
-    BdsLoadOption->FilePathListLength = GetDevicePathSize (BdsLoadOption->FilePathList);
-  } else {
-    if (SupportedBdsLoadOptionCount > 1) {
-      for (Index = 0; Index < SupportedBdsLoadOptionCount; Index++) {
-        Print (L"[%d] %s\n",Index + 1,SupportedBdsLoadOptions[Index]->Description);
-      }
-
-      do {
-        Print (L"Update Boot Entry: ");
-        Status = GetHIInputInteger (&Choice);
-        if (Status == EFI_INVALID_PARAMETER) {
-          Print (L"\n");
-          return Status;
-        } else if ((Choice < 1) && (Choice > SupportedBdsLoadOptionCount)) {
-          Print (L"Choose entry from 1 to %d\n",SupportedBdsLoadOptionCount);
-          Status = EFI_INVALID_PARAMETER;
-        }
-      } while (EFI_ERROR(Status));
-      BdsLoadOption = SupportedBdsLoadOptions[Choice-1];
-    }
-    StrnCpy (Description, BdsLoadOption->Description, MAX_STR_INPUT);
-
-    LinuxOptionalData = (LINUX_LOADER_OPTIONAL_DATA*)BdsLoadOption->OptionalData;
-    if (LinuxOptionalData->CmdLineLength > 0) {
-      CopyMem (CmdLine, (CHAR8*)LinuxOptionalData + sizeof(LINUX_LOADER_OPTIONAL_DATA), LinuxOptionalData->CmdLineLength);
-    } else {
-      CmdLine[0] = '\0';
-    }
-
-    if (LinuxOptionalData->InitrdPathListLength > 0) {
-      CopyMem (Initrd, (CHAR8*)LinuxOptionalData + sizeof(LINUX_LOADER_OPTIONAL_DATA) + LinuxOptionalData->CmdLineLength, LinuxOptionalData->InitrdPathListLength);
-    } else {
-      Initrd[0] = L'\0';
-    }
-    DEBUG((EFI_D_ERROR,"L\n"));
-  }
-
-  // Description
-  Print (L"Description: ");
-  Status = EditHIInputStr (Description, MAX_STR_INPUT);
-  if (EFI_ERROR(Status)) {
-    return Status;
-  }
-  if (StrLen (Description) == 0) {
-    StrnCpy (Description, DEFAULT_BOOT_ENTRY_DESCRIPTION, MAX_STR_INPUT);
-  }
-  BdsLoadOption->Description = Description;
-
-  // CmdLine
-  Print (L"Command Line: ");
-  Status = EditHIInputAscii (CmdLine, MAX_ASCII_INPUT);
-  if (EFI_ERROR(Status)) {
-    return Status;
-  }
-
-  // Initrd
-  Print (L"Initrd name: ");
-  Status = EditHIInputStr (Initrd, MAX_STR_INPUT);
-  if (EFI_ERROR(Status)) {
-    return Status;
-  }
-
-  CmdLineLength = AsciiStrLen (CmdLine);
-  if (CmdLineLength > 0) {
-    CmdLineLength += sizeof(CHAR8);
-  }
-
-  InitrdPathListLength = StrLen (Initrd) * sizeof(CHAR16);
-  if (InitrdPathListLength > 0) {
-    InitrdPathListLength += sizeof(CHAR16);
-  }
-
-  BdsLoadOption->OptionalDataSize = sizeof(LINUX_LOADER_OPTIONAL_DATA) + CmdLineLength + InitrdPathListLength;
-
-  LinuxOptionalData = (LINUX_LOADER_OPTIONAL_DATA*)AllocatePool (BdsLoadOption->OptionalDataSize);
-  BdsLoadOption->OptionalData = LinuxOptionalData;
-
-  LinuxOptionalData->Signature = LINUX_LOADER_SIGNATURE;
-  LinuxOptionalData->CmdLineLength = CmdLineLength;
-  LinuxOptionalData->InitrdPathListLength = InitrdPathListLength;
-
-  if (CmdLineLength > 0) {
-    CopyMem (LinuxOptionalData + 1, CmdLine, CmdLineLength);
-  }
-  if (InitrdPathListLength > 0) {
-    CopyMem ((UINT8*)(LinuxOptionalData + 1) + CmdLineLength, Initrd, InitrdPathListLength);
-  }
-
-  // Create or Update the boot entry
-  Status = BootOptionToLoadOptionVariable (BdsLoadOption);
-
-  return Status;
-}
+/** @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 "LinuxInternal.h"\r
+\r
+#define DEFAULT_BOOT_ENTRY_DESCRIPTION  L"Linux"\r
+#define MAX_STR_INPUT                   300\r
+#define MAX_ASCII_INPUT                 300\r
+\r
+typedef enum {\r
+  LINUX_LOADER_NEW = 1,\r
+  LINUX_LOADER_UPDATE\r
+} LINUX_LOADER_ACTION;\r
+\r
+STATIC\r
+EFI_STATUS\r
+EditHIInputStr (\r
+  IN OUT CHAR16  *CmdLine,\r
+  IN     UINTN   MaxCmdLine\r
+  )\r
+{\r
+  UINTN           CmdLineIndex;\r
+  UINTN           WaitIndex;\r
+  CHAR8           Char;\r
+  EFI_INPUT_KEY   Key;\r
+  EFI_STATUS      Status;\r
+\r
+  Print (CmdLine);\r
+\r
+  for (CmdLineIndex = StrLen (CmdLine); CmdLineIndex < MaxCmdLine; ) {\r
+    Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &WaitIndex);\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    // Unicode character is valid when Scancode is NUll\r
+    if (Key.ScanCode == SCAN_NULL) {\r
+      // Scan code is NUll, hence read Unicode character\r
+      Char = (CHAR8)Key.UnicodeChar;\r
+    } else {\r
+      Char = CHAR_NULL;\r
+    }\r
+\r
+    if ((Char == CHAR_LINEFEED) || (Char == CHAR_CARRIAGE_RETURN) || (Char == 0x7f)) {\r
+      CmdLine[CmdLineIndex] = '\0';\r
+      Print (L"\n\r");\r
+\r
+      return EFI_SUCCESS;\r
+    } else if ((Key.UnicodeChar == L'\b') || (Key.ScanCode == SCAN_LEFT) || (Key.ScanCode == SCAN_DELETE)){\r
+      if (CmdLineIndex != 0) {\r
+        CmdLineIndex--;\r
+        Print (L"\b \b");\r
+      }\r
+    } else if ((Key.ScanCode == SCAN_ESC) || (Char == 0x1B) || (Char == 0x0)) {\r
+      return EFI_INVALID_PARAMETER;\r
+    } else {\r
+      CmdLine[CmdLineIndex++] = Key.UnicodeChar;\r
+      Print (L"%c", Key.UnicodeChar);\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EditHIInputAscii (\r
+  IN OUT CHAR8   *CmdLine,\r
+  IN     UINTN   MaxCmdLine\r
+  )\r
+{\r
+  CHAR16*     Str;\r
+  EFI_STATUS  Status;\r
+\r
+  Str = (CHAR16*)AllocatePool (MaxCmdLine * sizeof(CHAR16));\r
+  AsciiStrToUnicodeStr (CmdLine, Str);\r
+\r
+  Status = EditHIInputStr (Str, MaxCmdLine);\r
+\r
+  UnicodeStrToAsciiStr (Str, CmdLine);\r
+  FreePool (Str);\r
+\r
+  return Status;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+GetHIInputInteger (\r
+  OUT UINTN   *Integer\r
+  )\r
+{\r
+  CHAR16      CmdLine[255];\r
+  EFI_STATUS  Status;\r
+\r
+  CmdLine[0] = '\0';\r
+  Status = EditHIInputStr (CmdLine, 255);\r
+  if (!EFI_ERROR(Status)) {\r
+    *Integer = StrDecimalToUintn (CmdLine);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+#if 0\r
+EFI_STATUS\r
+GenerateDeviceDescriptionName (\r
+  IN  EFI_HANDLE  Handle,\r
+  IN OUT CHAR16*  Description\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_COMPONENT_NAME_PROTOCOL*      ComponentName2Protocol;\r
+  EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;\r
+  EFI_DEVICE_PATH_PROTOCOL*         DevicePathProtocol;\r
+  CHAR16*                           DriverName;\r
+  CHAR16*                           DevicePathTxt;\r
+  EFI_DEVICE_PATH*                  DevicePathNode;\r
+\r
+  ComponentName2Protocol = NULL;\r
+  Status = gBS->HandleProtocol (Handle, &gEfiComponentName2ProtocolGuid, (VOID **)&ComponentName2Protocol);\r
+  if (!EFI_ERROR(Status)) {\r
+    //TODO: Fixme. we must find the best langague\r
+    Status = ComponentName2Protocol->GetDriverName (ComponentName2Protocol,"en",&DriverName);\r
+    if (!EFI_ERROR(Status)) {\r
+      StrnCpy (Description,DriverName,BOOT_DEVICE_DESCRIPTION_MAX);\r
+    }\r
+  }\r
+\r
+  if (EFI_ERROR(Status)) {\r
+    // Use the lastest non null entry of the Device path as a description\r
+    Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);\r
+    if (EFI_ERROR(Status)) {\r
+      return Status;\r
+    }\r
+\r
+    // Convert the last non end-type Device Path Node in text for the description\r
+    DevicePathNode = GetLastDevicePathNode (DevicePathProtocol);\r
+    Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);\r
+    ASSERT_EFI_ERROR(Status);\r
+    DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText(DevicePathNode,TRUE,TRUE);\r
+    StrnCpy (Description, DevicePathTxt, BOOT_DEVICE_DESCRIPTION_MAX);\r
+    FreePool (DevicePathTxt);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+#endif\r
+\r
+EFI_STATUS\r
+LinuxLoaderConfig (\r
+  IN EFI_LOADED_IMAGE_PROTOCOL   *LoadedImage\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  LINUX_LOADER_ACTION          Choice;\r
+  UINTN                        BootOrderSize;\r
+  UINT16*                      BootOrder;\r
+  UINTN                        BootOrderCount;\r
+  UINTN                        Index;\r
+  CHAR16                       Description[MAX_ASCII_INPUT];\r
+  CHAR8                        CmdLine[MAX_ASCII_INPUT];\r
+  CHAR16                       Initrd[MAX_STR_INPUT];\r
+  UINT16                       InitrdPathListLength;\r
+  UINT16                       CmdLineLength;\r
+  BDS_LOAD_OPTION*             BdsLoadOption;\r
+  BDS_LOAD_OPTION**            SupportedBdsLoadOptions;\r
+  UINTN                        SupportedBdsLoadOptionCount;\r
+  LINUX_LOADER_OPTIONAL_DATA*  LinuxOptionalData;\r
+  EFI_DEVICE_PATH*             DevicePathRoot;\r
+\r
+  SupportedBdsLoadOptions = NULL;\r
+  SupportedBdsLoadOptionCount = 0;\r
+\r
+  do {\r
+    Print (L"[%d] Create new Linux Boot Entry\n",LINUX_LOADER_NEW);\r
+    Print (L"[%d] Update Linux Boot Entry\n",LINUX_LOADER_UPDATE);\r
+\r
+    Print (L"Option: ");\r
+    Status = GetHIInputInteger (&Choice);\r
+    if (Status == EFI_INVALID_PARAMETER) {\r
+      Print (L"\n");\r
+      return Status;\r
+    } else if ((Choice != LINUX_LOADER_NEW) && (Choice != LINUX_LOADER_UPDATE)) {\r
+      Print (L"Error: the option should be either '%d' or '%d'\n",LINUX_LOADER_NEW,LINUX_LOADER_UPDATE);\r
+      Status = EFI_INVALID_PARAMETER;\r
+    }\r
+  } while (EFI_ERROR(Status));\r
+\r
+  if (Choice == LINUX_LOADER_UPDATE) {\r
+    // If no compatible entry then we just create a new entry\r
+    Choice = LINUX_LOADER_NEW;\r
+\r
+    // Scan the OptionalData of every entry for the correct signature\r
+    Status = GetEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);\r
+    if (!EFI_ERROR(Status)) {\r
+      BootOrderCount = BootOrderSize / sizeof(UINT16);\r
+\r
+      // Allocate an array to handle maximum number of supported Boot Entry\r
+      SupportedBdsLoadOptions = (BDS_LOAD_OPTION**)AllocatePool(sizeof(BDS_LOAD_OPTION*) * BootOrderCount);\r
+\r
+      SupportedBdsLoadOptionCount = 0;\r
+\r
+      // Check if the signature is present in the list of the current Boot entries\r
+      for (Index = 0; Index < BootOrderCount; Index++) {\r
+        Status = BootOptionFromLoadOptionIndex (BootOrder[Index], &BdsLoadOption);\r
+        if (!EFI_ERROR(Status)) {\r
+          if ((BdsLoadOption->OptionalDataSize >= sizeof(UINT32)) &&\r
+              (*(UINT32*)BdsLoadOption->OptionalData == LINUX_LOADER_SIGNATURE)) {\r
+            SupportedBdsLoadOptions[SupportedBdsLoadOptionCount++] = BdsLoadOption;\r
+            Choice = LINUX_LOADER_UPDATE;\r
+          }\r
+        }\r
+      }\r
+    }\r
+    FreePool (BootOrder);\r
+  }\r
+\r
+  if (Choice == LINUX_LOADER_NEW) {\r
+    Description[0] = '\0';\r
+    CmdLine[0]     = '\0';\r
+    Initrd[0]      = '\0';\r
+\r
+    BdsLoadOption = (BDS_LOAD_OPTION*)AllocateZeroPool (sizeof(BDS_LOAD_OPTION));\r
+\r
+    DEBUG_CODE_BEGIN();\r
+      CHAR16*                           DevicePathTxt;\r
+      EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;\r
+\r
+      Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);\r
+      ASSERT_EFI_ERROR(Status);\r
+      DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (LoadedImage->FilePath, TRUE, TRUE);\r
+\r
+      Print(L"EFI OS Loader: %s\n",DevicePathTxt);\r
+\r
+      FreePool(DevicePathTxt);\r
+    DEBUG_CODE_END();\r
+\r
+    //\r
+    // Fill the known fields of BdsLoadOption\r
+    //\r
+\r
+    BdsLoadOption->Attributes = LOAD_OPTION_ACTIVE | LOAD_OPTION_CATEGORY_BOOT;\r
+\r
+    // Get the full Device Path for this file\r
+    Status = gBS->HandleProtocol (LoadedImage->DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathRoot);\r
+    ASSERT_EFI_ERROR(Status);\r
+\r
+    BdsLoadOption->FilePathList = AppendDevicePath (DevicePathRoot, LoadedImage->FilePath);\r
+    BdsLoadOption->FilePathListLength = GetDevicePathSize (BdsLoadOption->FilePathList);\r
+  } else {\r
+    if (SupportedBdsLoadOptionCount > 1) {\r
+      for (Index = 0; Index < SupportedBdsLoadOptionCount; Index++) {\r
+        Print (L"[%d] %s\n",Index + 1,SupportedBdsLoadOptions[Index]->Description);\r
+      }\r
+\r
+      do {\r
+        Print (L"Update Boot Entry: ");\r
+        Status = GetHIInputInteger (&Choice);\r
+        if (Status == EFI_INVALID_PARAMETER) {\r
+          Print (L"\n");\r
+          return Status;\r
+        } else if ((Choice < 1) && (Choice > SupportedBdsLoadOptionCount)) {\r
+          Print (L"Choose entry from 1 to %d\n",SupportedBdsLoadOptionCount);\r
+          Status = EFI_INVALID_PARAMETER;\r
+        }\r
+      } while (EFI_ERROR(Status));\r
+      BdsLoadOption = SupportedBdsLoadOptions[Choice-1];\r
+    }\r
+    StrnCpy (Description, BdsLoadOption->Description, MAX_STR_INPUT);\r
+\r
+    LinuxOptionalData = (LINUX_LOADER_OPTIONAL_DATA*)BdsLoadOption->OptionalData;\r
+    if (LinuxOptionalData->CmdLineLength > 0) {\r
+      CopyMem (CmdLine, (CHAR8*)LinuxOptionalData + sizeof(LINUX_LOADER_OPTIONAL_DATA), LinuxOptionalData->CmdLineLength);\r
+    } else {\r
+      CmdLine[0] = '\0';\r
+    }\r
+\r
+    if (LinuxOptionalData->InitrdPathListLength > 0) {\r
+      CopyMem (Initrd, (CHAR8*)LinuxOptionalData + sizeof(LINUX_LOADER_OPTIONAL_DATA) + LinuxOptionalData->CmdLineLength, LinuxOptionalData->InitrdPathListLength);\r
+    } else {\r
+      Initrd[0] = L'\0';\r
+    }\r
+    DEBUG((EFI_D_ERROR,"L\n"));\r
+  }\r
+\r
+  // Description\r
+  Print (L"Description: ");\r
+  Status = EditHIInputStr (Description, MAX_STR_INPUT);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+  if (StrLen (Description) == 0) {\r
+    StrnCpy (Description, DEFAULT_BOOT_ENTRY_DESCRIPTION, MAX_STR_INPUT);\r
+  }\r
+  BdsLoadOption->Description = Description;\r
+\r
+  // CmdLine\r
+  Print (L"Command Line: ");\r
+  Status = EditHIInputAscii (CmdLine, MAX_ASCII_INPUT);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  // Initrd\r
+  Print (L"Initrd name: ");\r
+  Status = EditHIInputStr (Initrd, MAX_STR_INPUT);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  CmdLineLength = AsciiStrLen (CmdLine);\r
+  if (CmdLineLength > 0) {\r
+    CmdLineLength += sizeof(CHAR8);\r
+  }\r
+\r
+  InitrdPathListLength = StrLen (Initrd) * sizeof(CHAR16);\r
+  if (InitrdPathListLength > 0) {\r
+    InitrdPathListLength += sizeof(CHAR16);\r
+  }\r
+\r
+  BdsLoadOption->OptionalDataSize = sizeof(LINUX_LOADER_OPTIONAL_DATA) + CmdLineLength + InitrdPathListLength;\r
+\r
+  LinuxOptionalData = (LINUX_LOADER_OPTIONAL_DATA*)AllocatePool (BdsLoadOption->OptionalDataSize);\r
+  BdsLoadOption->OptionalData = LinuxOptionalData;\r
+\r
+  LinuxOptionalData->Signature = LINUX_LOADER_SIGNATURE;\r
+  LinuxOptionalData->CmdLineLength = CmdLineLength;\r
+  LinuxOptionalData->InitrdPathListLength = InitrdPathListLength;\r
+\r
+  if (CmdLineLength > 0) {\r
+    CopyMem (LinuxOptionalData + 1, CmdLine, CmdLineLength);\r
+  }\r
+  if (InitrdPathListLength > 0) {\r
+    CopyMem ((UINT8*)(LinuxOptionalData + 1) + CmdLineLength, Initrd, InitrdPathListLength);\r
+  }\r
+\r
+  // Create or Update the boot entry\r
+  Status = BootOptionToLoadOptionVariable (BdsLoadOption);\r
+\r
+  return Status;\r
+}\r