]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPlatformPkg/Bds/BootMenu.c
AppPkg: Update email and URL.
[mirror_edk2.git] / ArmPlatformPkg / Bds / BootMenu.c
index 04a2eee6f5a88217369a68533ce9345c4e85f54f..5cbac1d2dc1ab91be8ae402bb0e41e888d95aa38 100644 (file)
@@ -14,9 +14,7 @@
 \r
 #include "BdsInternal.h"\r
 \r
-#include <Guid/ArmGlobalVariableHob.h>\r
-\r
-extern BDS_LOAD_OPTION_SUPPORT *BdsLoadOptionSupportList;\r
+#include <libfdt.h>\r
 \r
 /**\r
   Worker function that displays the list of boot options that is passed in.\r
@@ -54,8 +52,6 @@ DisplayBootOptions (
     DEBUG_CODE_BEGIN ();\r
       CHAR16*                           DevicePathTxt;\r
       EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;\r
-      ARM_BDS_LOADER_TYPE               LoaderType;\r
-      ARM_BDS_LOADER_OPTIONAL_DATA*     OptionalData;\r
 \r
       Status = gBS->LocateProtocol (\r
                      &gEfiDevicePathToTextProtocolGuid,\r
@@ -70,20 +66,11 @@ DisplayBootOptions (
                                                   );\r
       Print (L"\t- %s\n", DevicePathTxt);\r
 \r
-      OptionalData = BdsLoadOption->OptionalData;\r
-      if (IS_ARM_BDS_BOOTENTRY (BdsLoadOption)) {\r
-        LoaderType = (ARM_BDS_LOADER_TYPE)ReadUnaligned32 ((CONST UINT32*)&OptionalData->Header.LoaderType);\r
-        if ((LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) ||\r
-            (LoaderType == BDS_LOADER_KERNEL_LINUX_FDT )   ) {\r
-          Print (L"\t- Arguments: %a\n", &OptionalData->Arguments.LinuxArguments + 1);\r
-        }\r
-      } else if (OptionalData != NULL) {\r
-        if (IsPrintableString (OptionalData, &IsUnicode)) {\r
-          if (IsUnicode) {\r
-            Print (L"\t- Arguments: %s\n", OptionalData);\r
-          } else {\r
-            AsciiPrint ("\t- Arguments: %a\n", OptionalData);\r
-          }\r
+      if (IsPrintableString (BdsLoadOption->OptionalData, &IsUnicode)) {\r
+        if (IsUnicode) {\r
+          Print (L"\t- Arguments: %s\n", BdsLoadOption->OptionalData);\r
+        } else {\r
+          AsciiPrint ("\t- Arguments: %a\n", BdsLoadOption->OptionalData);\r
         }\r
       }\r
 \r
@@ -272,22 +259,16 @@ BootMenuAddBootOption (
 {\r
   EFI_STATUS                Status;\r
   BDS_SUPPORTED_DEVICE*     SupportedBootDevice;\r
-  ARM_BDS_LOADER_ARGUMENTS* BootArguments;\r
   CHAR16                    BootDescription[BOOT_DEVICE_DESCRIPTION_MAX];\r
-  CHAR8                     AsciiCmdLine[BOOT_DEVICE_OPTION_MAX];\r
   CHAR16                    CmdLine[BOOT_DEVICE_OPTION_MAX];\r
   UINT32                    Attributes;\r
-  ARM_BDS_LOADER_TYPE       BootType;\r
   BDS_LOAD_OPTION_ENTRY     *BdsLoadOptionEntry;\r
   EFI_DEVICE_PATH           *DevicePath;\r
   EFI_DEVICE_PATH_PROTOCOL  *DevicePathNodes;\r
-  EFI_DEVICE_PATH_PROTOCOL  *InitrdPathNodes;\r
-  EFI_DEVICE_PATH_PROTOCOL  *InitrdPath;\r
-  UINTN                     CmdLineSize;\r
-  BOOLEAN                   InitrdSupport;\r
-  UINTN                     InitrdSize;\r
   UINT8*                    OptionalData;\r
   UINTN                     OptionalDataSize;\r
+  BOOLEAN                   EfiBinary;\r
+  CHAR16                    *LinuxDevicePath;\r
 \r
   Attributes                = 0;\r
   SupportedBootDevice = NULL;\r
@@ -300,8 +281,12 @@ BootMenuAddBootOption (
   }\r
 \r
   // Create the specific device path node\r
-  Status = SupportedBootDevice->Support->CreateDevicePathNode (L"EFI Application or the kernel", &DevicePathNodes);\r
-  if (EFI_ERROR(Status)) {\r
+  if (FeaturePcdGet (PcdBdsLinuxSupport) && mLinuxLoaderDevicePath) {\r
+    Status = SupportedBootDevice->Support->CreateDevicePathNode (L"EFI Application or the kernel", &DevicePathNodes);\r
+  } else {\r
+    Status = SupportedBootDevice->Support->CreateDevicePathNode (L"EFI Application", &DevicePathNodes);\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
     Status = EFI_ABORTED;\r
     goto EXIT;\r
   }\r
@@ -312,80 +297,47 @@ BootMenuAddBootOption (
     goto EXIT;\r
   }\r
 \r
-  if (SupportedBootDevice->Support->RequestBootType) {\r
-    Status = BootDeviceGetType (DevicePath, &BootType, &Attributes);\r
-    if (EFI_ERROR(Status)) {\r
-      Status = EFI_ABORTED;\r
-      goto EXIT;\r
-    }\r
-  } else {\r
-    BootType = BDS_LOADER_EFI_APPLICATION;\r
-  }\r
-\r
-  if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) {\r
-    Print(L"Add an initrd: ");\r
-    Status = GetHIInputBoolean (&InitrdSupport);\r
-    if (EFI_ERROR(Status)) {\r
+  // Is it an EFI application?\r
+  if (FeaturePcdGet (PcdBdsLinuxSupport) && mLinuxLoaderDevicePath) {\r
+    Status = IsEfiBinary (DevicePath, &EfiBinary);\r
+    if (EFI_ERROR (Status)) {\r
       Status = EFI_ABORTED;\r
       goto EXIT;\r
     }\r
 \r
-    if (InitrdSupport) {\r
-      // Create the specific device path node\r
-      Status = SupportedBootDevice->Support->CreateDevicePathNode (L"initrd", &InitrdPathNodes);\r
-      if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) { // EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd\r
-        Status = EFI_ABORTED;\r
-        goto EXIT;\r
-      }\r
-\r
-      if (InitrdPathNodes != NULL) {\r
-        // Append the Device Path to the selected device path\r
-        InitrdPath = AppendDevicePath (SupportedBootDevice->DevicePathProtocol, (CONST EFI_DEVICE_PATH_PROTOCOL *)InitrdPathNodes);\r
-        // Free the InitrdPathNodes created by Support->CreateDevicePathNode()\r
-        FreePool (InitrdPathNodes);\r
-\r
-        if (InitrdPath == NULL) {\r
-          Status = EFI_OUT_OF_RESOURCES;\r
-          goto EXIT;\r
-        }\r
-      } else {\r
-        InitrdPath = NULL;\r
-      }\r
+    if (EfiBinary == FALSE) {\r
+      Print (L"It is assumed the binary is a Linux kernel and the embedded Linux Loader is going to be used.\n");\r
+      Print (L"Supported command line formats by the embedded Linux Loader:\n");\r
+      Print (L"- <EFI device path of the Linux kernel> -c \"<Linux kernel command line>\"\n");\r
+      Print (L"- <EFI device path of the Linux kernel> -c \"<Linux kernel command line>\" -f <EFI Device Path of the Linux initrd>\n");\r
+      Print (L"- <EFI device path of the Linux kernel> -c \"<Linux kernel command line>\" -a <Machine Type for ATAG Linux kernel>\n");\r
+\r
+      // Copy the Linux path into the command line\r
+      LinuxDevicePath = ConvertDevicePathToText (DevicePath, FALSE, FALSE);\r
+      CopyMem (CmdLine, LinuxDevicePath, MAX (sizeof (CmdLine), StrSize (LinuxDevicePath)));\r
+      FreePool (LinuxDevicePath);\r
+\r
+      // Free the generated Device Path\r
+      FreePool (DevicePath);\r
+      // and use the embedded Linux Loader as the EFI application\r
+      DevicePath = mLinuxLoaderDevicePath;\r
     } else {\r
-      InitrdPath = NULL;\r
-    }\r
-\r
-    Print(L"Arguments to pass to the binary: ");\r
-    Status = GetHIInputAscii (AsciiCmdLine, BOOT_DEVICE_OPTION_MAX);\r
-    if (EFI_ERROR(Status)) {\r
-      Status = EFI_ABORTED;\r
-      goto FREE_DEVICE_PATH;\r
+      CmdLine[0] = L'\0';\r
     }\r
-\r
-    CmdLineSize = AsciiStrSize (AsciiCmdLine);\r
-    InitrdSize = GetDevicePathSize (InitrdPath);\r
-\r
-    OptionalDataSize = sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize;\r
-    BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (OptionalDataSize);\r
-\r
-    BootArguments->LinuxArguments.CmdLineSize = CmdLineSize;\r
-    BootArguments->LinuxArguments.InitrdSize = InitrdSize;\r
-    CopyMem ((VOID*)(&BootArguments->LinuxArguments + 1), AsciiCmdLine, CmdLineSize);\r
-    CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize), InitrdPath, InitrdSize);\r
-\r
-    OptionalData = (UINT8*)BootArguments;\r
   } else {\r
-    Print (L"Arguments to pass to the EFI Application: ");\r
-    Status = GetHIInputStr (CmdLine, BOOT_DEVICE_OPTION_MAX);\r
-    if (EFI_ERROR (Status)) {\r
-      Status = EFI_ABORTED;\r
-      goto EXIT;\r
-    }\r
+    CmdLine[0] = L'\0';\r
+  }\r
 \r
-    OptionalData = (UINT8*)CmdLine;\r
-    OptionalDataSize = StrSize (CmdLine);\r
+  Print (L"Arguments to pass to the EFI Application: ");\r
+  Status = EditHIInputStr (CmdLine, BOOT_DEVICE_OPTION_MAX);\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_ABORTED;\r
+    goto EXIT;\r
   }\r
 \r
+  OptionalData = (UINT8*)CmdLine;\r
+  OptionalDataSize = StrSize (CmdLine);\r
+\r
   Print(L"Description for this new Entry: ");\r
   Status = GetHIInputStr (BootDescription, BOOT_DEVICE_DESCRIPTION_MAX);\r
   if (EFI_ERROR(Status)) {\r
@@ -395,7 +347,7 @@ BootMenuAddBootOption (
 \r
   // Create new entry\r
   BdsLoadOptionEntry = (BDS_LOAD_OPTION_ENTRY*)AllocatePool (sizeof(BDS_LOAD_OPTION_ENTRY));\r
-  Status = BootOptionCreate (Attributes, BootDescription, DevicePath, BootType, OptionalData, OptionalDataSize, &BdsLoadOptionEntry->BdsLoadOption);\r
+  Status = BootOptionCreate (Attributes, BootDescription, DevicePath, OptionalData, OptionalDataSize, &BdsLoadOptionEntry->BdsLoadOption);\r
   if (!EFI_ERROR(Status)) {\r
     InsertTailList (BootOptionsList, &BdsLoadOptionEntry->Link);\r
   }\r
@@ -446,24 +398,16 @@ BootMenuUpdateBootOption (
   BDS_LOAD_OPTION_ENTRY         *BootOptionEntry;\r
   BDS_LOAD_OPTION               *BootOption;\r
   BDS_LOAD_OPTION_SUPPORT*      DeviceSupport;\r
-  ARM_BDS_LOADER_ARGUMENTS*     BootArguments;\r
   CHAR16                        BootDescription[BOOT_DEVICE_DESCRIPTION_MAX];\r
   CHAR8                         CmdLine[BOOT_DEVICE_OPTION_MAX];\r
   CHAR16                        UnicodeCmdLine[BOOT_DEVICE_OPTION_MAX];\r
+  CHAR16                        *LinuxDevicePath;\r
   EFI_DEVICE_PATH               *DevicePath;\r
-  EFI_DEVICE_PATH               *TempInitrdPath;\r
-  ARM_BDS_LOADER_TYPE           BootType;\r
-  ARM_BDS_LOADER_OPTIONAL_DATA* LoaderOptionalData;\r
-  ARM_BDS_LINUX_ARGUMENTS*      LinuxArguments;\r
-  EFI_DEVICE_PATH               *InitrdPathNodes;\r
-  EFI_DEVICE_PATH               *InitrdPath;\r
-  UINTN                         InitrdSize;\r
-  UINTN                         CmdLineSize;\r
-  BOOLEAN                       InitrdSupport;\r
   UINT8*                        OptionalData;\r
   UINTN                         OptionalDataSize;\r
   BOOLEAN                       IsPrintable;\r
   BOOLEAN                       IsUnicode;\r
+  BOOLEAN                       EfiBinary;\r
 \r
   DisplayBootOptions (BootOptionsList);\r
   Status = SelectBootOption (BootOptionsList, UPDATE_BOOT_ENTRY, &BootOptionEntry);\r
@@ -479,111 +423,54 @@ BootMenuUpdateBootOption (
     return EFI_UNSUPPORTED;\r
   }\r
 \r
-  Status = DeviceSupport->UpdateDevicePathNode (BootOption->FilePathList, L"EFI Application or the kernel", &DevicePath);\r
-  if (EFI_ERROR(Status)) {\r
-    Status = EFI_ABORTED;\r
-    goto EXIT;\r
-  }\r
-\r
-  if (DeviceSupport->RequestBootType) {\r
-    Status = BootDeviceGetType (DevicePath, &BootType, &BootOption->Attributes);\r
-    if (EFI_ERROR(Status)) {\r
+  EfiBinary = TRUE;\r
+  if (FeaturePcdGet (PcdBdsLinuxSupport) && mLinuxLoaderDevicePath) {\r
+    Status = DeviceSupport->UpdateDevicePathNode (BootOption->FilePathList, L"EFI Application or the kernel", &DevicePath);\r
+    if (EFI_ERROR (Status)) {\r
       Status = EFI_ABORTED;\r
       goto EXIT;\r
     }\r
-  }\r
-\r
-  LoaderOptionalData = BootOption->OptionalData;\r
-  if (LoaderOptionalData != NULL) {\r
-    BootType = (ARM_BDS_LOADER_TYPE)ReadUnaligned32 ((UINT32 *)(&LoaderOptionalData->Header.LoaderType));\r
-  } else {\r
-    BootType = BDS_LOADER_EFI_APPLICATION;\r
-  }\r
-\r
-  if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) {\r
-    LinuxArguments = &LoaderOptionalData->Arguments.LinuxArguments;\r
 \r
-    CmdLineSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->CmdLineSize);\r
-\r
-    InitrdSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->InitrdSize);\r
-    if (InitrdSize > 0) {\r
-      Print(L"Keep the initrd: ");\r
-    } else {\r
-      Print(L"Add an initrd: ");\r
-    }\r
-    Status = GetHIInputBoolean (&InitrdSupport);\r
-    if (EFI_ERROR(Status)) {\r
+    // Is it an EFI application?\r
+    Status = IsEfiBinary (DevicePath, &EfiBinary);\r
+    if (EFI_ERROR (Status)) {\r
       Status = EFI_ABORTED;\r
       goto EXIT;\r
     }\r
 \r
-    if (InitrdSupport) {\r
-      if (InitrdSize > 0) {\r
-        // Case we update the initrd device path\r
-        Status = DeviceSupport->UpdateDevicePathNode ((EFI_DEVICE_PATH*)((UINTN)(LinuxArguments + 1) + CmdLineSize), L"initrd", &InitrdPath);\r
-        if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) {// EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd\r
-          Status = EFI_ABORTED;\r
-          goto EXIT;\r
-        }\r
-        InitrdSize = GetDevicePathSize (InitrdPath);\r
-      } else {\r
-        // Case we create the initrd device path\r
+    if (EfiBinary == FALSE) {\r
+      Print (L"It is assumed the binary is a Linux kernel and the embedded Linux Loader is going to be used.\n");\r
+      Print (L"Supported command line formats by the embedded Linux Loader:\n");\r
+      Print (L"- <EFI device path of the Linux kernel> -c \"<Linux kernel command line>\"\n");\r
+      Print (L"- <EFI device path of the Linux kernel> -c \"<Linux kernel command line>\" -f <EFI Device Path of the Linux initrd>\n");\r
+      Print (L"- <EFI device path of the Linux kernel> -c \"<Linux kernel command line>\" -a <Machine Type for ATAG Linux kernel>\n");\r
 \r
-        Status = DeviceSupport->CreateDevicePathNode (L"initrd", &InitrdPathNodes);\r
-        if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) { // EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd\r
-          Status = EFI_ABORTED;\r
-          goto EXIT;\r
-        }\r
+      // Copy the Linux path into the command line\r
+      LinuxDevicePath = ConvertDevicePathToText (DevicePath, FALSE, FALSE);\r
+      CopyMem (UnicodeCmdLine, LinuxDevicePath, MAX (sizeof (UnicodeCmdLine), StrSize (LinuxDevicePath)));\r
+      FreePool (LinuxDevicePath);\r
 \r
-        if (InitrdPathNodes != NULL) {\r
-          // Duplicate Linux kernel Device Path\r
-          TempInitrdPath = DuplicateDevicePath (BootOption->FilePathList);\r
-          // Replace Linux kernel Node by EndNode\r
-          SetDevicePathEndNode (GetLastDevicePathNode (TempInitrdPath));\r
-          // Append the Device Path to the selected device path\r
-          InitrdPath = AppendDevicePath (TempInitrdPath, (CONST EFI_DEVICE_PATH_PROTOCOL *)InitrdPathNodes);\r
-          FreePool (TempInitrdPath);\r
-          // Free the InitrdPathNodes created by Support->CreateDevicePathNode()\r
-          FreePool (InitrdPathNodes);\r
-          if (InitrdPath == NULL) {\r
-            Status = EFI_OUT_OF_RESOURCES;\r
-            goto EXIT;\r
-          }\r
-          InitrdSize = GetDevicePathSize (InitrdPath);\r
-        } else {\r
-          InitrdPath = NULL;\r
-        }\r
-      }\r
-    } else {\r
-      InitrdSize = 0;\r
-    }\r
+      // Free the generated Device Path\r
+      FreePool (DevicePath);\r
+      // and use the embedded Linux Loader as the EFI application\r
+      DevicePath = mLinuxLoaderDevicePath;\r
 \r
-    Print(L"Arguments to pass to the binary: ");\r
-    if (CmdLineSize > 0) {\r
-      AsciiStrnCpy (CmdLine, (CONST CHAR8*)(LinuxArguments + 1), sizeof (CmdLine));\r
-      CmdLine[sizeof (CmdLine) - 1] = '\0';\r
-    } else {\r
-      CmdLine[0] = '\0';\r
+      // The command line is a unicode printable string\r
+      IsPrintable = TRUE;\r
+      IsUnicode = TRUE;\r
     }\r
-    Status = EditHIInputAscii (CmdLine, BOOT_DEVICE_OPTION_MAX);\r
-    if (EFI_ERROR(Status)) {\r
+  } else {\r
+    Status = DeviceSupport->UpdateDevicePathNode (BootOption->FilePathList, L"EFI Application", &DevicePath);\r
+    if (EFI_ERROR (Status)) {\r
       Status = EFI_ABORTED;\r
-      goto FREE_DEVICE_PATH;\r
+      goto EXIT;\r
     }\r
+  }\r
 \r
-    CmdLineSize = AsciiStrSize (CmdLine);\r
-\r
-    OptionalDataSize = sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize;\r
-    BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (OptionalDataSize);\r
-    BootArguments->LinuxArguments.CmdLineSize = CmdLineSize;\r
-    BootArguments->LinuxArguments.InitrdSize = InitrdSize;\r
-    CopyMem (&BootArguments->LinuxArguments + 1, CmdLine, CmdLineSize);\r
-    CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize), InitrdPath, InitrdSize);\r
-\r
-    OptionalData = (UINT8*)BootArguments;\r
-  } else {\r
-    Print (L"Arguments to pass to the EFI Application: ");\r
+  Print (L"Arguments to pass to the EFI Application: ");\r
 \r
+  // When the command line has not been initialized by the embedded Linux loader earlier\r
+  if (EfiBinary) {\r
     if (BootOption->OptionalDataSize > 0) {\r
       IsPrintable = IsPrintableString (BootOption->OptionalData, &IsUnicode);\r
       if (IsPrintable) {\r
@@ -617,33 +504,33 @@ BootMenuUpdateBootOption (
       IsPrintable = TRUE;\r
       IsUnicode = TRUE;\r
     }\r
+  }\r
 \r
-    // We do not request arguments for OptionalData that cannot be printed\r
-    if (IsPrintable) {\r
-      if (IsUnicode) {\r
-        Status = EditHIInputStr (UnicodeCmdLine, BOOT_DEVICE_OPTION_MAX);\r
-        if (EFI_ERROR (Status)) {\r
-          Status = EFI_ABORTED;\r
-          goto FREE_DEVICE_PATH;\r
-        }\r
-\r
-        OptionalData = (UINT8*)UnicodeCmdLine;\r
-        OptionalDataSize = StrSize (UnicodeCmdLine);\r
-      } else {\r
-        Status = EditHIInputAscii (CmdLine, BOOT_DEVICE_OPTION_MAX);\r
-        if (EFI_ERROR (Status)) {\r
-          Status = EFI_ABORTED;\r
-          goto FREE_DEVICE_PATH;\r
-        }\r
-\r
-        OptionalData = (UINT8*)CmdLine;\r
-        OptionalDataSize = AsciiStrSize (CmdLine);\r
+  // We do not request arguments for OptionalData that cannot be printed\r
+  if (IsPrintable) {\r
+    if (IsUnicode) {\r
+      Status = EditHIInputStr (UnicodeCmdLine, BOOT_DEVICE_OPTION_MAX);\r
+      if (EFI_ERROR (Status)) {\r
+        Status = EFI_ABORTED;\r
+        goto FREE_DEVICE_PATH;\r
       }\r
+\r
+      OptionalData = (UINT8*)UnicodeCmdLine;\r
+      OptionalDataSize = StrSize (UnicodeCmdLine);\r
     } else {\r
-      // We keep the former OptionalData\r
-      OptionalData = BootOption->OptionalData;\r
-      OptionalDataSize = BootOption->OptionalDataSize;\r
+      Status = EditHIInputAscii (CmdLine, BOOT_DEVICE_OPTION_MAX);\r
+      if (EFI_ERROR (Status)) {\r
+        Status = EFI_ABORTED;\r
+        goto FREE_DEVICE_PATH;\r
+      }\r
+\r
+      OptionalData = (UINT8*)CmdLine;\r
+      OptionalDataSize = AsciiStrSize (CmdLine);\r
     }\r
+  } else {\r
+    // We keep the former OptionalData\r
+    OptionalData = BootOption->OptionalData;\r
+    OptionalDataSize = BootOption->OptionalDataSize;\r
   }\r
 \r
   Print(L"Description for this new Entry: ");\r
@@ -655,7 +542,7 @@ BootMenuUpdateBootOption (
   }\r
 \r
   // Update the entry\r
-  Status = BootOptionUpdate (BootOption, BootOption->Attributes, BootDescription, DevicePath, BootType, OptionalData, OptionalDataSize);\r
+  Status = BootOptionUpdate (BootOption, BootOption->Attributes, BootDescription, DevicePath, OptionalData, OptionalDataSize);\r
 \r
 FREE_DEVICE_PATH:\r
   FreePool (DevicePath);\r
@@ -830,54 +717,143 @@ UpdateFdtPath (
   )\r
 {\r
   EFI_STATUS                Status;\r
-  UINTN                     FdtDevicePathSize;\r
   BDS_SUPPORTED_DEVICE      *SupportedBootDevice;\r
   EFI_DEVICE_PATH_PROTOCOL  *FdtDevicePathNodes;\r
   EFI_DEVICE_PATH_PROTOCOL  *FdtDevicePath;\r
+  CHAR16                    *FdtTextDevicePath;\r
+  EFI_PHYSICAL_ADDRESS      FdtBlobBase;\r
+  UINTN                     FdtBlobSize;\r
+  UINTN                     NumPages;\r
+  EFI_PHYSICAL_ADDRESS      FdtConfigurationTableBase;\r
+\r
+  SupportedBootDevice = NULL;\r
 \r
   Status = SelectBootDevice (&SupportedBootDevice);\r
-  if (EFI_ERROR(Status)) {\r
+  if (EFI_ERROR (Status)) {\r
     Status = EFI_ABORTED;\r
     goto EXIT;\r
   }\r
 \r
   // Create the specific device path node\r
   Status = SupportedBootDevice->Support->CreateDevicePathNode (L"FDT blob", &FdtDevicePathNodes);\r
-  if (EFI_ERROR(Status)) {\r
+  if (EFI_ERROR (Status)) {\r
     Status = EFI_ABORTED;\r
     goto EXIT;\r
   }\r
 \r
   if (FdtDevicePathNodes != NULL) {\r
-    // Append the Device Path node to the select device path\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+\r
     FdtDevicePath = AppendDevicePath (SupportedBootDevice->DevicePathProtocol, FdtDevicePathNodes);\r
-    // Free the FdtDevicePathNodes created by Support->CreateDevicePathNode()\r
     FreePool (FdtDevicePathNodes);\r
-    FdtDevicePathSize = GetDevicePathSize (FdtDevicePath);\r
+    if (FdtDevicePath == NULL) {\r
+      goto EXIT;\r
+    }\r
+\r
+    FdtTextDevicePath = ConvertDevicePathToText (FdtDevicePath, TRUE, TRUE);\r
+    if (FdtTextDevicePath == NULL) {\r
+      goto EXIT;\r
+    }\r
+\r
     Status = gRT->SetVariable (\r
                     (CHAR16*)L"Fdt",\r
-                    &gArmGlobalVariableGuid,\r
-                    EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
-                    FdtDevicePathSize,\r
-                    FdtDevicePath\r
+                    &gFdtVariableGuid,\r
+                    EFI_VARIABLE_RUNTIME_ACCESS |\r
+                    EFI_VARIABLE_NON_VOLATILE   |\r
+                    EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+                    StrSize (FdtTextDevicePath),\r
+                    FdtTextDevicePath\r
                     );\r
-    ASSERT_EFI_ERROR(Status);\r
+    ASSERT_EFI_ERROR (Status);\r
+    FreePool (FdtTextDevicePath);\r
   } else {\r
     Status = gRT->SetVariable (\r
            (CHAR16*)L"Fdt",\r
-           &gArmGlobalVariableGuid,\r
-           EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+           &gFdtVariableGuid,\r
+           EFI_VARIABLE_RUNTIME_ACCESS |\r
+           EFI_VARIABLE_NON_VOLATILE   |\r
+           EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
            0,\r
            NULL\r
            );\r
-    ASSERT_EFI_ERROR(Status);\r
+    ASSERT_EFI_ERROR (Status);\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Try to load FDT from the new EFI Device Path\r
+  //\r
+\r
+  //\r
+  // Load the FDT given its device path.\r
+  // This operation may fail if the device path is not supported.\r
+  //\r
+  FdtBlobBase = 0;\r
+  NumPages    = 0;\r
+  Status = BdsLoadImage (FdtDevicePath, AllocateAnyPages, &FdtBlobBase, &FdtBlobSize);\r
+  FreePool (FdtDevicePath);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto EXIT_LOAD_FDT;\r
+  }\r
+\r
+  // Check the FDT header is valid. We only make this check in DEBUG mode in\r
+  // case the FDT header change on production device and this ASSERT() becomes\r
+  // not valid.\r
+  ASSERT (fdt_check_header ((VOID*)(UINTN)FdtBlobBase) == 0);\r
+\r
+  //\r
+  // Ensure the Size of the Device Tree is smaller than the size of the read file\r
+  //\r
+  ASSERT ((UINTN)fdt_totalsize ((VOID*)(UINTN)FdtBlobBase) <= FdtBlobSize);\r
+\r
+  //\r
+  // Store the FDT as Runtime Service Data to prevent the Kernel from\r
+  // overwritting its data.\r
+  //\r
+  NumPages = EFI_SIZE_TO_PAGES (FdtBlobSize);\r
+  Status = gBS->AllocatePages (\r
+                  AllocateAnyPages, EfiRuntimeServicesData,\r
+                  NumPages, &FdtConfigurationTableBase\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto EXIT_LOAD_FDT;\r
+  }\r
+  gBS->CopyMem (\r
+    (VOID*)(UINTN)FdtConfigurationTableBase,\r
+    (VOID*)(UINTN)FdtBlobBase,\r
+    FdtBlobSize\r
+    );\r
+\r
+  //\r
+  // Install the FDT into the Configuration Table\r
+  //\r
+  Status = gBS->InstallConfigurationTable (\r
+                  &gFdtTableGuid,\r
+                  (VOID*)(UINTN)FdtConfigurationTableBase\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    gBS->FreePages (FdtConfigurationTableBase, NumPages);\r
+  }\r
+\r
+EXIT_LOAD_FDT:\r
+  if (EFI_ERROR (Status)) {\r
+    Print (L"\nWarning: Did not manage to install the new device tree. Try to restart the platform.\n");\r
+  }\r
+\r
+  if (FdtBlobBase != 0) {\r
+    gBS->FreePages (FdtBlobBase, NumPages);\r
   }\r
 \r
 EXIT:\r
   if (Status == EFI_ABORTED) {\r
-    Print(L"\n");\r
+    Print (L"\n");\r
   }\r
-  FreePool(SupportedBootDevice);\r
+\r
+  if (SupportedBootDevice != NULL) {\r
+    FreePool (SupportedBootDevice);\r
+  }\r
+\r
   return Status;\r
 }\r
 \r
@@ -980,17 +956,27 @@ BootShell (
   IN LIST_ENTRY *BootOptionsList\r
   )\r
 {\r
-  EFI_STATUS Status;\r
+  EFI_STATUS       Status;\r
+  EFI_DEVICE_PATH* EfiShellDevicePath;\r
 \r
-  // Start EFI Shell\r
-  Status = BdsLoadApplication (gImageHandle, L"Shell", 0, NULL);\r
+  // Find the EFI Shell\r
+  Status = LocateEfiApplicationInFvByName (L"Shell", &EfiShellDevicePath);\r
   if (Status == EFI_NOT_FOUND) {\r
     Print (L"Error: EFI Application not found.\n");\r
-  } else if (EFI_ERROR(Status)) {\r
-    Print (L"Error: Status Code: 0x%X\n",(UINT32)Status);\r
-  }\r
+    return Status;\r
+  } else if (EFI_ERROR (Status)) {\r
+    Print (L"Error: Status Code: 0x%X\n", (UINT32)Status);\r
+    return Status;\r
+  } else {\r
+    // Need to connect every drivers to ensure no dependencies are missing for the application\r
+    Status = BdsConnectAllDrivers ();\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "FAIL to connect all drivers\n"));\r
+      return Status;\r
+    }\r
 \r
-  return Status;\r
+    return BdsStartEfiApplication (gImageHandle, EfiShellDevicePath, 0, NULL);\r
+  }\r
 }\r
 \r
 struct BOOT_MAIN_ENTRY {\r
@@ -1001,7 +987,6 @@ struct BOOT_MAIN_ENTRY {
     { L"Boot Manager", BootMenuManager },\r
 };\r
 \r
-\r
 EFI_STATUS\r
 BootMenuMain (\r
   VOID\r
@@ -1021,6 +1006,12 @@ BootMenuMain (
   BootOption         = NULL;\r
   BootMainEntryCount = sizeof(BootMainEntries) / sizeof(struct BOOT_MAIN_ENTRY);\r
 \r
+  if (FeaturePcdGet (PcdBdsLinuxSupport)) {\r
+    // Check Linux Loader is present\r
+    Status = LocateEfiApplicationInFvByGuid (&mLinuxLoaderAppGuid, &mLinuxLoaderDevicePath);\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
   while (TRUE) {\r
     // Get Boot#### list\r
     BootOptionList (&BootOptionsList);\r
@@ -1040,9 +1031,6 @@ BootMenuMain (
       DEBUG_CODE_BEGIN();\r
         CHAR16*                           DevicePathTxt;\r
         EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;\r
-        ARM_BDS_LOADER_OPTIONAL_DATA*     OptionalData;\r
-        UINTN                             CmdLineSize;\r
-        ARM_BDS_LOADER_TYPE               LoaderType;\r
 \r
         Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);\r
         if (EFI_ERROR(Status)) {\r
@@ -1054,39 +1042,7 @@ BootMenuMain (
 \r
         Print(L"\t- %s\n",DevicePathTxt);\r
 \r
-        // If it is a supported BootEntry then print its details\r
-        if (IS_ARM_BDS_BOOTENTRY (BootOption)) {\r
-          OptionalData = BootOption->OptionalData;\r
-          LoaderType = (ARM_BDS_LOADER_TYPE)ReadUnaligned32 ((CONST UINT32*)&OptionalData->Header.LoaderType);\r
-          if ((LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) || (LoaderType == BDS_LOADER_KERNEL_LINUX_FDT)) {\r
-            if (ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.InitrdSize) > 0) {\r
-              CmdLineSize = ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.CmdLineSize);\r
-              DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (\r
-                  GetAlignedDevicePath ((EFI_DEVICE_PATH*)((UINTN)(&OptionalData->Arguments.LinuxArguments + 1) + CmdLineSize)), TRUE, TRUE);\r
-              Print(L"\t- Initrd: %s\n", DevicePathTxt);\r
-            }\r
-            if (ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.CmdLineSize) > 0) {\r
-              Print(L"\t- Arguments: %a\n", (&OptionalData->Arguments.LinuxArguments + 1));\r
-            }\r
-          }\r
-\r
-          switch (LoaderType) {\r
-            case BDS_LOADER_EFI_APPLICATION:\r
-              Print(L"\t- LoaderType: EFI Application\n");\r
-              break;\r
-\r
-            case BDS_LOADER_KERNEL_LINUX_ATAG:\r
-              Print(L"\t- LoaderType: Linux kernel with ATAG support\n");\r
-              break;\r
-\r
-            case BDS_LOADER_KERNEL_LINUX_FDT:\r
-              Print(L"\t- LoaderType: Linux kernel with FDT support\n");\r
-              break;\r
-\r
-            default:\r
-              Print(L"\t- LoaderType: Not recognized (%d)\n", LoaderType);\r
-          }\r
-        } else if (BootOption->OptionalData != NULL) {\r
+        if (BootOption->OptionalData != NULL) {\r
           if (IsPrintableString (BootOption->OptionalData, &IsUnicode)) {\r
             if (IsUnicode) {\r
               Print (L"\t- Arguments: %s\n", BootOption->OptionalData);\r