diff --git a/ArmPlatformPkg/ArmPlatformPkg.dec b/ArmPlatformPkg/ArmPlatformPkg.dec
index 3e2900b..e672ce2 100644
--- a/ArmPlatformPkg/ArmPlatformPkg.dec
+++ b/ArmPlatformPkg/ArmPlatformPkg.dec
@@ -136,6 +136,8 @@
   gArmPlatformTokenSpaceGuid.PcdDefaultBootType|0|UINT32|0x00000010
   gArmPlatformTokenSpaceGuid.PcdFdtDevicePath|L""|VOID*|0x00000011
   
+  gArmPlatformTokenSpaceGuid.PcdDefaultFdtLocalDevicePath|L""|VOID*|0x0000002E
+
   ## Timeout value for displaying progressing bar in before boot OS.
   #  According to UEFI 2.0 spec, the default TimeOut should be 0xffff.
   gArmPlatformTokenSpaceGuid.PcdPlatformBootTimeOut|0xffff|UINT16|0x0000001A
diff --git a/ArmPlatformPkg/Bds/Bds.c b/ArmPlatformPkg/Bds/Bds.c
index 2801fac..d0fc6a3 100644
--- a/ArmPlatformPkg/Bds/Bds.c
+++ b/ArmPlatformPkg/Bds/Bds.c
@@ -223,8 +223,10 @@ DefineDefaultBootEntries (
   ARM_BDS_LOADER_ARGUMENTS*           BootArguments;
   ARM_BDS_LOADER_TYPE                 BootType;
   EFI_DEVICE_PATH*                    InitrdPath;
+  EFI_DEVICE_PATH*                    FdtLocalPath;
   UINTN                               CmdLineSize;
   UINTN                               InitrdSize;
+  UINTN                               FdtLocalSize;
 
   //
   // If Boot Order does not exist then create a default entry
@@ -262,17 +264,30 @@ DefineDefaultBootEntries (
     if (BootDevicePath != NULL) {
       BootType = (ARM_BDS_LOADER_TYPE)PcdGet32 (PcdDefaultBootType);
 
-      if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) {
+      if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT) || (BootType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT)) {
         CmdLineSize = AsciiStrSize ((CHAR8*)PcdGetPtr(PcdDefaultBootArgument));
         InitrdPath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdDefaultBootInitrdPath));
         InitrdSize = GetDevicePathSize (InitrdPath);
+        if (BootType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT) {
+          FdtLocalPath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdDefaultFdtLocalDevicePath));
+          FdtLocalSize = GetDevicePathSize (FdtLocalPath);
+        } else {
+          FdtLocalPath = NULL;
+          FdtLocalSize = 0;
+        }
 
-        BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize);
-        BootArguments->LinuxArguments.CmdLineSize = CmdLineSize;
-        BootArguments->LinuxArguments.InitrdSize = InitrdSize;
-
-        CopyMem ((VOID*)(BootArguments + 1), (CHAR8*)PcdGetPtr(PcdDefaultBootArgument), CmdLineSize);
-        CopyMem ((VOID*)((UINTN)(BootArguments + 1) + CmdLineSize), InitrdPath, InitrdSize);
+        BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize + FdtLocalSize);
+        if ( BootArguments != NULL ) {
+          BootArguments->LinuxArguments.CmdLineSize = CmdLineSize;
+          BootArguments->LinuxArguments.InitrdSize = InitrdSize;
+          BootArguments->LinuxArguments.FdtLocalSize = FdtLocalSize;
+
+          CopyMem ((VOID*)(BootArguments + 1), (CHAR8*)PcdGetPtr(PcdDefaultBootArgument), CmdLineSize);
+          CopyMem ((VOID*)((UINTN)(BootArguments + 1) + CmdLineSize), InitrdPath, InitrdSize);
+          CopyMem ((VOID*)((UINTN)(BootArguments + 1) + CmdLineSize + InitrdSize), FdtLocalPath, FdtLocalSize);
+        }
+        FreePool (FdtLocalPath);
+        FreePool (InitrdPath);
       } else {
         BootArguments = NULL;
       }
@@ -285,6 +300,7 @@ DefineDefaultBootEntries (
         &BdsLoadOption
         );
       FreePool (BdsLoadOption);
+      FreePool (BootDevicePath);
     } else {
       Status = EFI_UNSUPPORTED;
     }
diff --git a/ArmPlatformPkg/Bds/Bds.inf b/ArmPlatformPkg/Bds/Bds.inf
index 5faa4b2..8b3f1d2 100644
--- a/ArmPlatformPkg/Bds/Bds.inf
+++ b/ArmPlatformPkg/Bds/Bds.inf
@@ -68,6 +68,7 @@
   gArmPlatformTokenSpaceGuid.PcdDefaultBootArgument
   gArmPlatformTokenSpaceGuid.PcdDefaultBootType
   gArmPlatformTokenSpaceGuid.PcdFdtDevicePath
+  gArmPlatformTokenSpaceGuid.PcdDefaultFdtLocalDevicePath
   gArmPlatformTokenSpaceGuid.PcdPlatformBootTimeOut
   gArmPlatformTokenSpaceGuid.PcdDefaultConInPaths
   gArmPlatformTokenSpaceGuid.PcdDefaultConOutPaths
diff --git a/ArmPlatformPkg/Bds/BdsInternal.h b/ArmPlatformPkg/Bds/BdsInternal.h
index a8d836d..7830066 100644
--- a/ArmPlatformPkg/Bds/BdsInternal.h
+++ b/ArmPlatformPkg/Bds/BdsInternal.h
@@ -38,6 +38,11 @@
 #define BOOT_DEVICE_OPTION_MAX        300
 #define BOOT_DEVICE_ADDRESS_MAX       (sizeof(L"0x0000000000000000"))
 
+// Length of the buffer used to hold the user input for the main menu
+// This includes the NULL terminator
+// 1 chars + newline + NULL gives room for up to 9 boot device configs
+#define BOOT_OPTION_LEN   3
+
 #define ARM_BDS_OPTIONAL_DATA_SIGNATURE   SIGNATURE_32('a', 'b', 'o', 'd')
 
 #define IS_ARM_BDS_BOOTENTRY(ptr)  (ReadUnaligned32 ((CONST UINT32*)&((ARM_BDS_LOADER_OPTIONAL_DATA*)((ptr)->OptionalData))->Header.Signature) == ARM_BDS_OPTIONAL_DATA_SIGNATURE)
@@ -48,16 +53,20 @@
 typedef enum {
     BDS_LOADER_EFI_APPLICATION = 0,
     BDS_LOADER_KERNEL_LINUX_ATAG,
-    BDS_LOADER_KERNEL_LINUX_FDT,
+    BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT,
+    BDS_LOADER_KERNEL_LINUX_LOCAL_FDT,
 } ARM_BDS_LOADER_TYPE;
 
 typedef struct {
   UINT16                     CmdLineSize;
   UINT16                     InitrdSize;
 
+  UINT16                     FdtLocalSize;
+
   // These following fields have variable length and are packed:
   //CHAR8                      *CmdLine;
   //EFI_DEVICE_PATH_PROTOCOL   *InitrdPathList;
+  //EFI_DEVICE_PATH_PROTOCOL   *FdtLocalPathList;
 } ARM_BDS_LINUX_ARGUMENTS;
 
 typedef union {
diff --git a/ArmPlatformPkg/Bds/BootMenu.c b/ArmPlatformPkg/Bds/BootMenu.c
index 2b32e83..de2117b 100644
--- a/ArmPlatformPkg/Bds/BootMenu.c
+++ b/ArmPlatformPkg/Bds/BootMenu.c
@@ -128,9 +128,12 @@ BootMenuAddBootOption (
   EFI_DEVICE_PATH_PROTOCOL  *DevicePathNodes;
   EFI_DEVICE_PATH_PROTOCOL  *InitrdPathNodes;
   EFI_DEVICE_PATH_PROTOCOL  *InitrdPath;
+  EFI_DEVICE_PATH_PROTOCOL  *FdtLocalPathNode;
+  EFI_DEVICE_PATH_PROTOCOL  *FdtLocalPath;
   UINTN                     CmdLineSize;
   BOOLEAN                   InitrdSupport;
   UINTN                     InitrdSize;
+  UINTN                     FdtLocalSize;
 
   Attributes                = 0;
   SupportedBootDevice = NULL;
@@ -155,12 +158,12 @@ BootMenuAddBootOption (
     goto EXIT;
   }
 
-  if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) {
+  if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT) || (BootType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT)) {
     Print(L"Add an initrd: ");
     Status = GetHIInputBoolean (&InitrdSupport);
     if (EFI_ERROR(Status)) {
       Status = EFI_ABORTED;
-      goto EXIT;
+      goto FREE_DEVICE_PATH;
     }
 
     if (InitrdSupport) {
@@ -168,7 +171,7 @@ BootMenuAddBootOption (
       Status = SupportedBootDevice->Support->CreateDevicePathNode (L"initrd", &InitrdPathNodes, NULL, NULL);
       if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) { // EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd
         Status = EFI_ABORTED;
-        goto EXIT;
+        goto FREE_DEVICE_PATH;
       }
 
       if (InitrdPathNodes != NULL) {
@@ -176,7 +179,7 @@ BootMenuAddBootOption (
         InitrdPath = AppendDevicePath (SupportedBootDevice->DevicePathProtocol, (CONST EFI_DEVICE_PATH_PROTOCOL *)InitrdPathNodes);
         if (InitrdPath == NULL) {
           Status = EFI_OUT_OF_RESOURCES;
-          goto EXIT;
+          goto FREE_DEVICE_PATH;
         }
       } else {
         InitrdPath = NULL;
@@ -192,15 +195,37 @@ BootMenuAddBootOption (
       goto FREE_DEVICE_PATH;
     }
 
-    CmdLineSize = AsciiStrSize (CmdLine);
-    InitrdSize = GetDevicePathSize (InitrdPath);
+    if (BootType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT) {
+      // Create the specific device path node
+      Status = SupportedBootDevice->Support->CreateDevicePathNode (L"local FDT", &FdtLocalPathNode, NULL, NULL);
+      if (EFI_ERROR(Status) || (FdtLocalPathNode == NULL)) {
+        Status = EFI_ABORTED;
+        goto FREE_DEVICE_PATH;
+      }
 
-    BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize);
+      if (FdtLocalPathNode != NULL) {
+        // Append the Device Path node to the select device path
+        FdtLocalPath = AppendDevicePathNode (SupportedBootDevice->DevicePathProtocol, (CONST EFI_DEVICE_PATH_PROTOCOL *)FdtLocalPathNode);
+      } else {
+        FdtLocalPath = NULL;
+      }
+    } else {
+      FdtLocalPath = NULL;
+    }
 
-    BootArguments->LinuxArguments.CmdLineSize = CmdLineSize;
-    BootArguments->LinuxArguments.InitrdSize = InitrdSize;
-    CopyMem ((VOID*)(&BootArguments->LinuxArguments + 1), CmdLine, CmdLineSize);
-    CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize), InitrdPath, InitrdSize);
+    CmdLineSize = AsciiStrSize (CmdLine);
+    InitrdSize = GetDevicePathSize (InitrdPath);
+    FdtLocalSize = GetDevicePathSize (FdtLocalPath);
+
+    BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize + FdtLocalSize);
+    if ( BootArguments != NULL ) {
+      BootArguments->LinuxArguments.CmdLineSize = CmdLineSize;
+      BootArguments->LinuxArguments.InitrdSize = InitrdSize;
+      BootArguments->LinuxArguments.FdtLocalSize = FdtLocalSize;
+      CopyMem ((VOID*)(&BootArguments->LinuxArguments + 1), CmdLine, CmdLineSize);
+      CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize), InitrdPath, InitrdSize);
+      CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize + InitrdSize), FdtLocalPath, FdtLocalSize);
+    }
   } else {
     BootArguments = NULL;
   }
@@ -214,6 +239,10 @@ BootMenuAddBootOption (
 
   // Create new entry
   BdsLoadOptionEntry = (BDS_LOAD_OPTION_ENTRY*)AllocatePool (sizeof(BDS_LOAD_OPTION_ENTRY));
+  if ( BdsLoadOptionEntry == NULL ) {
+    Status = EFI_ABORTED;
+    goto FREE_DEVICE_PATH;
+  }
   Status = BootOptionCreate (Attributes, BootDescription, DevicePath, BootType, BootArguments, &BdsLoadOptionEntry->BdsLoadOption);
   if (!EFI_ERROR(Status)) {
     InsertTailList (BootOptionsList, &BdsLoadOptionEntry->Link);
@@ -274,7 +303,7 @@ BootMenuSelectBootOption (
       Print(L"\t- %s\n",DevicePathTxt);
       OptionalData = BdsLoadOption->OptionalData;
       LoaderType = (ARM_BDS_LOADER_TYPE)ReadUnaligned32 ((CONST UINT32*)&OptionalData->Header.LoaderType);
-      if ((LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) || (LoaderType == BDS_LOADER_KERNEL_LINUX_FDT)) {
+      if ((LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) || (LoaderType == BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT) || (LoaderType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT)) {
         Print (L"\t- Arguments: %a\n",&OptionalData->Arguments.LinuxArguments + 1);
       }
 
@@ -366,14 +395,19 @@ BootMenuUpdateBootOption (
   CHAR8                         CmdLine[BOOT_DEVICE_OPTION_MAX];
   EFI_DEVICE_PATH               *DevicePath;
   EFI_DEVICE_PATH               *TempInitrdPath;
+  EFI_DEVICE_PATH               *TempFdtLocalPath;
   ARM_BDS_LOADER_TYPE           BootType;
   ARM_BDS_LOADER_OPTIONAL_DATA* OptionalData;
   ARM_BDS_LINUX_ARGUMENTS*      LinuxArguments;
   EFI_DEVICE_PATH               *InitrdPathNodes;
   EFI_DEVICE_PATH               *InitrdPath;
   UINTN                         InitrdSize;
+  EFI_DEVICE_PATH               *FdtLocalPathNode;
+  EFI_DEVICE_PATH               *FdtLocalPath;
+  UINTN                         FdtLocalSize;
   UINTN                         CmdLineSize;
   BOOLEAN                       InitrdSupport;
+  BOOLEAN                       FdtLocalSupport;
 
   Status = BootMenuSelectBootOption (BootOptionsList, UPDATE_BOOT_ENTRY, TRUE, &BootOptionEntry);
   if (EFI_ERROR(Status)) {
@@ -397,12 +431,65 @@ BootMenuUpdateBootOption (
   OptionalData = BootOption->OptionalData;
   BootType = (ARM_BDS_LOADER_TYPE)ReadUnaligned32 ((UINT32 *)(&OptionalData->Header.LoaderType));
 
-  if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) {
+  if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT) || (BootType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT)) {
     LinuxArguments = &OptionalData->Arguments.LinuxArguments;
 
     CmdLineSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->CmdLineSize);
 
     InitrdSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->InitrdSize);
+    FdtLocalSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->FdtLocalSize);
+
+    if (BootType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT) {
+      if (FdtLocalSize > 0) {
+        Print(L"Keep the local FDT: ");
+      } else {
+        Print(L"Add a local FDT: ");
+      }
+      Status = GetHIInputBoolean (&FdtLocalSupport);
+      if (EFI_ERROR(Status)) {
+        Status = EFI_ABORTED;
+        goto EXIT;
+      }
+      if (FdtLocalSupport && BootType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT) {
+        if (FdtLocalSize > 0) {
+          // Case we update the FDT local device path
+          Status = DeviceSupport->UpdateDevicePathNode ((EFI_DEVICE_PATH*)((UINTN)(LinuxArguments + 1) + CmdLineSize + InitrdSize), L"local FDT", &FdtLocalPath, NULL, NULL);
+          if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) {// EFI_NOT_FOUND is returned on empty input string
+            Status = EFI_ABORTED;
+            goto EXIT;
+          }
+          FdtLocalSize = GetDevicePathSize (FdtLocalPath);
+        } else {
+          // Case we create the FdtLocal device path
+
+          Status = DeviceSupport->CreateDevicePathNode (L"local FDT", &FdtLocalPathNode, NULL, NULL);
+          if (EFI_ERROR(Status) || (FdtLocalPathNode == NULL)) {
+            Status = EFI_ABORTED;
+            goto EXIT;
+          }
+
+          if (FdtLocalPathNode != NULL) {
+            // Duplicate Linux kernel Device Path
+            TempFdtLocalPath = DuplicateDevicePath (BootOption->FilePathList);
+            if ( TempFdtLocalPath != NULL ) {
+              // Replace Linux kernel Node by EndNode
+              SetDevicePathEndNode (GetLastDevicePathNode (TempFdtLocalPath));
+              // Append the Device Path node to the select device path
+              FdtLocalPath = AppendDevicePathNode (TempFdtLocalPath, (CONST EFI_DEVICE_PATH_PROTOCOL *)FdtLocalPathNode);
+              FreePool (TempFdtLocalPath);
+              FdtLocalSize = GetDevicePathSize (FdtLocalPath);
+            }
+          } else {
+            FdtLocalPath = NULL;
+          }
+        }
+      } else {
+        FdtLocalSize = 0;
+      }
+    } else {
+      FdtLocalSupport = FALSE;
+    }
+
     if (InitrdSize > 0) {
       Print(L"Keep the initrd: ");
     } else {
@@ -467,11 +554,15 @@ BootMenuUpdateBootOption (
 
     CmdLineSize = AsciiStrSize (CmdLine);
 
-    BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool(sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize);
-    BootArguments->LinuxArguments.CmdLineSize = CmdLineSize;
-    BootArguments->LinuxArguments.InitrdSize = InitrdSize;
-    CopyMem (&BootArguments->LinuxArguments + 1, CmdLine, CmdLineSize);
-    CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize), InitrdPath, InitrdSize);
+    BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool(sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize + FdtLocalSize);
+    if ( BootArguments != NULL ) {
+      BootArguments->LinuxArguments.CmdLineSize = CmdLineSize;
+      BootArguments->LinuxArguments.InitrdSize = InitrdSize;
+      BootArguments->LinuxArguments.FdtLocalSize = FdtLocalSize;
+      CopyMem (&BootArguments->LinuxArguments + 1, CmdLine, CmdLineSize);
+      CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize), InitrdPath, InitrdSize);
+      CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize + InitrdSize), FdtLocalPath, FdtLocalSize);
+    }
   } else {
     BootArguments = NULL;
   }
@@ -648,19 +739,20 @@ BootMenuMain (
   VOID
   )
 {
-  LIST_ENTRY                    BootOptionsList;
-  UINTN                         OptionCount;
-  UINTN                         HardCodedOptionCount;
-  UINTN                         BootOptionCount;
-  EFI_STATUS                    Status;
-  LIST_ENTRY*                   Entry;
-  BDS_LOAD_OPTION*              BootOption;
-  UINTN                         BootOptionSelected;
-  UINTN                         Index;
-  UINTN                         BootMainEntryCount;
-  CHAR8                         BootOptionSelectedStr[32];
-  EFI_DEVICE_PATH_PROTOCOL*     DefaultFdtDevicePath;
-  UINTN                         FdtDevicePathSize;
+  LIST_ENTRY                        BootOptionsList;
+  UINTN                             OptionCount;
+  UINTN                             BootOptionCount;
+  EFI_STATUS                        Status;
+  LIST_ENTRY*                       Entry;
+  BDS_LOAD_OPTION*                  BootOption;
+  UINTN                             BootOptionSelected;
+  UINTN                             Index;
+  UINTN                             BootMainEntryCount;
+  CHAR8                             BootOptionSelectedStr[BOOT_OPTION_LEN];
+  EFI_DEVICE_PATH_PROTOCOL*         DefaultFdtDevicePath;
+  UINTN                             FdtDevicePathSize;
+  EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;
+  CHAR16*                           DevicePathTxt;
 
 
   BootOption              = NULL;
@@ -682,11 +774,10 @@ BootMenuMain (
 
       Print(L"[%d] %s\n", OptionCount, BootOption->Description);
 
-      DEBUG_CODE_BEGIN();
-        CHAR16*                           DevicePathTxt;
-        EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;
+      //DEBUG_CODE_BEGIN();
         ARM_BDS_LOADER_OPTIONAL_DATA*     OptionalData;
         UINTN                             CmdLineSize;
+        UINTN                             InitrdSize;
         ARM_BDS_LOADER_TYPE               LoaderType;
 
         Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);
@@ -703,7 +794,7 @@ BootMenuMain (
         if (IS_ARM_BDS_BOOTENTRY (BootOption)) {
           OptionalData = BootOption->OptionalData;
           LoaderType = (ARM_BDS_LOADER_TYPE)ReadUnaligned32 ((CONST UINT32*)&OptionalData->Header.LoaderType);
-          if ((LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) || (LoaderType == BDS_LOADER_KERNEL_LINUX_FDT)) {
+          if ((LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) || (LoaderType == BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT) || (LoaderType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT)) {
             if (ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.InitrdSize) > 0) {
               CmdLineSize = ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.CmdLineSize);
               DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (
@@ -722,16 +813,28 @@ BootMenuMain (
               Print(L"\t- LoaderType: Linux kernel with ATAG support\n");
               break;
 
-            case BDS_LOADER_KERNEL_LINUX_FDT:
-              Print(L"\t- LoaderType: Linux kernel with FDT support\n");
+            case BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT:
+              Print(L"\t- LoaderType: Linux kernel with global FDT support\n");
+              break;
+            case BDS_LOADER_KERNEL_LINUX_LOCAL_FDT:
+              if (ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.FdtLocalSize) > 0) {
+                CmdLineSize = ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.CmdLineSize);
+                InitrdSize  = ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.InitrdSize);
+                DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (
+                    GetAlignedDevicePath ((EFI_DEVICE_PATH*)((UINTN)(&OptionalData->Arguments.LinuxArguments + 1) + CmdLineSize + InitrdSize)), TRUE, TRUE);
+                Print(L"\t- FDT: %s\n", DevicePathTxt);
+              } else {
+                Print(L"\t- FDT: error, local FDT not specified, using global FDT\n");
+              }
+              Print(L"\t- LoaderType: Linux kernel with Local FDT\n");
               break;
-
             default:
               Print(L"\t- LoaderType: Not recognized (%d)\n", LoaderType);
+              break;
           }
         }
         FreePool(DevicePathTxt);
-      DEBUG_CODE_END();
+      //DEBUG_CODE_END();
 
       OptionCount++;
     }
@@ -739,55 +842,56 @@ BootMenuMain (
 
     // Display the global FDT config
     Print(L"-----------------------\n");
-      {
-        EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL*   EfiDevicePathFromTextProtocol;
-        EFI_DEVICE_PATH_PROTOCOL*             FdtDevicePath;
-        EFI_DEVICE_PATH_TO_TEXT_PROTOCOL*     DevicePathToTextProtocol;
-        CHAR16*                               DevicePathTxt;
+    {
+      EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL*   EfiDevicePathFromTextProtocol;
+      EFI_DEVICE_PATH_PROTOCOL*             FdtDevicePath;
 
-        // Get the default FDT device path
-        Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol);
-        ASSERT_EFI_ERROR(Status);
-        DefaultFdtDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdFdtDevicePath));
+      // Get the default FDT device path
+      Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol);
+      ASSERT_EFI_ERROR(Status);
+      DefaultFdtDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdFdtDevicePath));
 
-        // Get the FDT device path
-        FdtDevicePathSize = GetDevicePathSize (DefaultFdtDevicePath);
-        Status = GetEnvironmentVariable ((CHAR16 *)L"Fdt", &gArmGlobalVariableGuid, DefaultFdtDevicePath, &FdtDevicePathSize, (VOID **)&FdtDevicePath);
+      // Get the FDT device path
+      FdtDevicePathSize = GetDevicePathSize (DefaultFdtDevicePath);
+      Status = GetEnvironmentVariable ((CHAR16 *)L"Fdt", &gArmGlobalVariableGuid, DefaultFdtDevicePath, &FdtDevicePathSize, (VOID **)&FdtDevicePath);
 
-        // Convert FdtDevicePath to text
-        if (EFI_ERROR(Status)) {
-          DevicePathTxt = L"not configured";
-        } else {
-          Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);
-          DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText ( FdtDevicePath, TRUE, TRUE );
-        }
-        Print(L"Global FDT Config\n\t- %s\n", DevicePathTxt);
+      // Convert FdtDevicePath to text
+      if (EFI_ERROR(Status)) {
+        DevicePathTxt = L"not configured";
+      } else {
+        Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);
+        DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText ( FdtDevicePath, TRUE, TRUE );
       }
+      Print(L"Global FDT Config\n\t- %s\n", DevicePathTxt);
+      FreePool(DevicePathTxt);
+      FreePool(DefaultFdtDevicePath);
+    }
 
     // Display the hardcoded Boot entries
     Print(L"-----------------------\n");
     for (Index = 0; Index < BootMainEntryCount; Index++) {
-      Print(L"[%c] %s\n", ('a'+Index), BootMainEntries[Index]);
+      Print(L"[%c] %s\n", ('a' + Index), BootMainEntries[Index]);
       OptionCount++;
     }
-    HardCodedOptionCount=Index;
 
     // Request the boot entry from the user
     BootOptionSelected = 0;
     while (BootOptionSelected == 0) {
       Print(L"Start: ");
-      Status = GetHIInputAscii (BootOptionSelectedStr,8);
+      Status = GetHIInputAscii (BootOptionSelectedStr, BOOT_OPTION_LEN);
 
-      if (BootOptionSelectedStr[0]-'0' <= OptionCount) {
-        BootOptionSelected = BootOptionSelectedStr[0] - '0';
-      } else if (BootOptionSelectedStr[0]-'a' <= HardCodedOptionCount) {
-        BootOptionSelected = BootOptionCount + 1 + BootOptionSelectedStr[0] - 'a';
-      }
+      if (!EFI_ERROR(Status)) {
+        if ((BootOptionSelectedStr[0] - '0') < OptionCount) {
+          BootOptionSelected = BootOptionSelectedStr[0] - '0';
+        } else if ((BootOptionSelectedStr[0] - 'a') < BootMainEntryCount) {
+          BootOptionSelected = BootOptionCount + 1 + BootOptionSelectedStr[0] - 'a';
+        }
 
-      if (EFI_ERROR(Status) || (BootOptionSelected == 0) || (BootOptionSelected > OptionCount)) {
-        Print(L"Invalid input (max %d)\n",(OptionCount-1));
-        BootOptionSelected = 0;
-      }
+        if ((BootOptionSelected == 0) || (BootOptionSelected > OptionCount)) {
+          Print(L"Invalid input, please choose a menu option from the list above\n");
+          BootOptionSelected = 0;
+        }
+      }
     }
 
     // Start the selected entry
diff --git a/ArmPlatformPkg/Bds/BootOption.c b/ArmPlatformPkg/Bds/BootOption.c
index ee0301e..6b756a3 100644
--- a/ArmPlatformPkg/Bds/BootOption.c
+++ b/ArmPlatformPkg/Bds/BootOption.c
@@ -33,6 +33,7 @@ BootOptionStart (
   UINTN                                 CmdLineSize;
   UINTN                                 InitrdSize;
   EFI_DEVICE_PATH*                      Initrd;
+  UINTN                                 FdtLocalSize;
   UINT16                                LoadOptionIndexSize;
 
   if (IS_ARM_BDS_BOOTENTRY (BootOption)) {
@@ -59,7 +60,7 @@ BootOptionStart (
       Status = BdsBootLinuxAtag (BootOption->FilePathList,
                                  Initrd, // Initrd
                                  (CHAR8*)(LinuxArguments + 1)); // CmdLine
-    } else if (LoaderType == BDS_LOADER_KERNEL_LINUX_FDT) {
+    } else if ((LoaderType == BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT) || (LoaderType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT)) {
       LinuxArguments = &(OptionalData->Arguments.LinuxArguments);
       CmdLineSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->CmdLineSize);
       InitrdSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->InitrdSize);
@@ -70,17 +71,27 @@ BootOptionStart (
         Initrd = NULL;
       }
 
-      // Get the default FDT device path
-      Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol);
-      ASSERT_EFI_ERROR(Status);
-      DefaultFdtDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdFdtDevicePath));
-
-      // Get the FDT device path
-      FdtDevicePathSize = GetDevicePathSize (DefaultFdtDevicePath);
-      Status = GetEnvironmentVariable ((CHAR16 *)L"Fdt", &gArmGlobalVariableGuid,
-                 DefaultFdtDevicePath, &FdtDevicePathSize, (VOID **)&FdtDevicePath);
-      ASSERT_EFI_ERROR(Status);
+      if (LoaderType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT) {
+        FdtLocalSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->FdtLocalSize);
 
+        if (FdtLocalSize > 0) {
+          FdtDevicePath = GetAlignedDevicePath ((EFI_DEVICE_PATH*)((UINTN)(LinuxArguments + 1) + CmdLineSize + InitrdSize));
+        } else {
+          FdtDevicePath = NULL;
+        }
+      } else  {
+        // Get the default FDT device path
+        Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol);
+        ASSERT_EFI_ERROR(Status);
+        DefaultFdtDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdFdtDevicePath));
+
+        // Get the FDT device path
+        FdtDevicePathSize = GetDevicePathSize (DefaultFdtDevicePath);
+        Status = GetEnvironmentVariable ((CHAR16 *)L"Fdt", &gArmGlobalVariableGuid,
+                   DefaultFdtDevicePath, &FdtDevicePathSize, (VOID **)&FdtDevicePath);
+        ASSERT_EFI_ERROR(Status);
+        FreePool (DefaultFdtDevicePath);
+      }
       Status = BdsBootLinuxFdt (BootOption->FilePathList,
                                 Initrd, // Initrd
                                 (CHAR8*)(LinuxArguments + 1),
@@ -159,6 +170,7 @@ BootOptionSetFields (
   UINT16                        FilePathListLength;
   UINT8*                        EfiLoadOptionPtr;
   UINT8*                        InitrdPathListPtr;
+  UINT8*                        FdtLocalPathListPtr;
   UINTN                         OptionalDataSize;
   ARM_BDS_LINUX_ARGUMENTS*      DestLinuxArguments;
   ARM_BDS_LINUX_ARGUMENTS*      SrcLinuxArguments;
@@ -170,8 +182,8 @@ BootOptionSetFields (
 
   BootDescriptionSize = StrSize (BootDescription);
   BootOptionalDataSize = sizeof(ARM_BDS_LOADER_OPTIONAL_DATA_HEADER);
-  if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) {
-    BootOptionalDataSize += sizeof(ARM_BDS_LINUX_ARGUMENTS) + BootArguments->LinuxArguments.CmdLineSize + BootArguments->LinuxArguments.InitrdSize;
+  if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT) || (BootType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT)) {
+    BootOptionalDataSize += sizeof(ARM_BDS_LINUX_ARGUMENTS) + BootArguments->LinuxArguments.CmdLineSize + BootArguments->LinuxArguments.InitrdSize + BootArguments->LinuxArguments.FdtLocalSize;
   }
 
   // Compute the size of the FilePath list
@@ -213,12 +225,13 @@ BootOptionSetFields (
 
   OptionalDataSize = sizeof(ARM_BDS_LOADER_OPTIONAL_DATA_HEADER);
 
-  if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) {
+  if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT) || (BootType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT)) {
     SrcLinuxArguments = &(BootArguments->LinuxArguments);
     DestLinuxArguments = &((ARM_BDS_LOADER_OPTIONAL_DATA*)EfiLoadOptionPtr)->Arguments.LinuxArguments;
 
     WriteUnaligned16 ((UINT16 *)&(DestLinuxArguments->CmdLineSize), SrcLinuxArguments->CmdLineSize);
     WriteUnaligned16 ((UINT16 *)&(DestLinuxArguments->InitrdSize), SrcLinuxArguments->InitrdSize);
+    WriteUnaligned16 ((UINT16 *)&(DestLinuxArguments->FdtLocalSize), SrcLinuxArguments->FdtLocalSize);
     OptionalDataSize += sizeof (ARM_BDS_LINUX_ARGUMENTS);
 
     if (SrcLinuxArguments->CmdLineSize > 0) {
@@ -230,6 +243,11 @@ BootOptionSetFields (
       InitrdPathListPtr = (UINT8*)((UINTN)(DestLinuxArguments + 1) + SrcLinuxArguments->CmdLineSize);
       CopyMem (InitrdPathListPtr, (VOID*)((UINTN)(SrcLinuxArguments + 1) + SrcLinuxArguments->CmdLineSize), SrcLinuxArguments->InitrdSize);
     }
+
+    if (SrcLinuxArguments->FdtLocalSize > 0) {
+      FdtLocalPathListPtr = (UINT8*)((UINTN)(DestLinuxArguments + 1) + SrcLinuxArguments->CmdLineSize + SrcLinuxArguments->InitrdSize);
+      CopyMem (FdtLocalPathListPtr, (VOID*)((UINTN)(SrcLinuxArguments + 1) + SrcLinuxArguments->CmdLineSize + SrcLinuxArguments->InitrdSize), SrcLinuxArguments->FdtLocalSize);
+    }
   }
   BootOption->OptionalDataSize = OptionalDataSize;
 
diff --git a/ArmPlatformPkg/Bds/BootOptionSupport.c b/ArmPlatformPkg/Bds/BootOptionSupport.c
index 190169a..c2df7f9 100644
--- a/ArmPlatformPkg/Bds/BootOptionSupport.c
+++ b/ArmPlatformPkg/Bds/BootOptionSupport.c
@@ -25,6 +25,7 @@
 #include <Guid/FileSystemInfo.h>
 
 #define IS_DEVICE_PATH_NODE(node,type,subtype) (((node)->Type == (type)) && ((node)->SubType == (subtype)))
+#define LOCAL_FDT_RESPONSE_LEN 2  // 1 character, plus carriage return
 
 EFI_STATUS
 BdsLoadOptionFileSystemList (
@@ -233,7 +234,7 @@ BootDeviceGetType (
   EFI_STATUS Status;
   BOOLEAN IsEfiApp;
   BOOLEAN IsBootLoader;
-  BOOLEAN     HasFDTSupport;
+  CHAR16  FDTType[ LOCAL_FDT_RESPONSE_LEN ];
 
   if (FileName == NULL) {
     Print(L"Is an EFI Application? ");
@@ -258,15 +259,19 @@ BootDeviceGetType (
     }
     *BootType = BDS_LOADER_EFI_APPLICATION;
   } else {
-    Print(L"Has FDT support? ");
-    Status = GetHIInputBoolean (&HasFDTSupport);
+    Print(L"Boot Type: [a] ATAGS, [g] Global FDT or [l] Local FDT? [a/g/l] ");
+    Status = GetHIInputStr (FDTType, LOCAL_FDT_RESPONSE_LEN );
     if (EFI_ERROR(Status)) {
       return EFI_ABORTED;
     }
-    if (HasFDTSupport) {
-      *BootType = BDS_LOADER_KERNEL_LINUX_FDT;
-    } else {
+    if (StrCmp(FDTType, L"g") == 0) {
+      *BootType = BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT;
+    } else if (StrCmp(FDTType, L"l") == 0) {
+      *BootType = BDS_LOADER_KERNEL_LINUX_LOCAL_FDT;
+    } else if (StrCmp(FDTType, L"a") == 0) {
       *BootType = BDS_LOADER_KERNEL_LINUX_ATAG;
+    } else {
+      return EFI_ABORTED;
     }
   }
 
