diff --git a/Platform/ARM/JunoPkg/AcpiTables/AcpiTables.inf b/Platform/ARM/JunoPkg/AcpiTables/AcpiTables.inf
index 741ea191be36..539974ff2416 100644
--- a/Platform/ARM/JunoPkg/AcpiTables/AcpiTables.inf
+++ b/Platform/ARM/JunoPkg/AcpiTables/AcpiTables.inf
@@ -33,11 +33,10 @@ [Sources]
 [Packages]
   ArmPkg/ArmPkg.dec
   ArmPlatformPkg/ArmPlatformPkg.dec
-  ArmPlatformPkg/ArmVExpressPkg/ArmVExpressPkg.dec
-  ArmPlatformPkg/ArmJunoPkg/ArmJuno.dec
   EmbeddedPkg/EmbeddedPkg.dec
   MdePkg/MdePkg.dec
   MdeModulePkg/MdeModulePkg.dec
+  Platform/ARM/JunoPkg/ArmJuno.dec
 
 [FixedPcd]
   gArmPlatformTokenSpaceGuid.PcdCoreCount
diff --git a/Platform/ARM/JunoPkg/ArmJuno.dec b/Platform/ARM/JunoPkg/ArmJuno.dec
new file mode 100644
index 000000000000..60cef6d23a2d
--- /dev/null
+++ b/Platform/ARM/JunoPkg/ArmJuno.dec
@@ -0,0 +1,48 @@
+#
+#  Copyright (c) 2013-2015, 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.
+#
+
+[Defines]
+  DEC_SPECIFICATION              = 0x0001001A
+  PACKAGE_NAME                   = ArmJunoPkg
+  PACKAGE_GUID                   = a1147a20-3144-4f8d-8295-b48311c8e4a4
+  PACKAGE_VERSION                = 0.1
+
+################################################################################
+#
+# Include Section - list of Include Paths that are provided by this package.
+#                   Comments are used for Keywords and Module Types.
+#
+# Supported Module Types:
+#  BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION
+#
+################################################################################
+[Includes.common]
+  Include                        # Root include for the package
+
+[Guids.common]
+  gArmJunoTokenSpaceGuid    =  { 0xa1147a20, 0x3144, 0x4f8d, { 0x82, 0x95, 0xb4, 0x83, 0x11, 0xc8, 0xe4, 0xa4 } }
+
+[PcdsFeatureFlag.common]
+  gArmJunoTokenSpaceGuid.PcdPciMaxPayloadFixup|FALSE|BOOLEAN|0x00000013
+
+[PcdsFixedAtBuild.common]
+  gArmJunoTokenSpaceGuid.PcdPcieControlBaseAddress|0x7FF20000|UINT64|0x0000000B
+  gArmJunoTokenSpaceGuid.PcdPcieRootPortBaseAddress|0x7FF30000|UINT64|0x0000000C
+  gArmJunoTokenSpaceGuid.PcdPciConfigurationSpaceBaseAddress|0x40000000|UINT64|0x00000011
+  gArmJunoTokenSpaceGuid.PcdPciConfigurationSpaceSize|0x10000000|UINT64|0x00000012
+
+  gArmJunoTokenSpaceGuid.PcdSynopsysUsbOhciBaseAddress|0x7FFB0000|UINT32|0x00000004
+  gArmJunoTokenSpaceGuid.PcdSynopsysUsbEhciBaseAddress|0x7FFC0000|UINT32|0x00000005
+
+  # Juno Device Trees are loaded from NOR Flash
+  gArmJunoTokenSpaceGuid.PcdJunoFdtDevicePath|L"VenHw(E7223039-5836-41E1-B542-D7EC736C5E59)/board.dtb"|VOID*|0x00000008
+
diff --git a/Platform/ARM/JunoPkg/ArmJuno.dsc b/Platform/ARM/JunoPkg/ArmJuno.dsc
index 881d1e67748f..187c9f5602e5 100644
--- a/Platform/ARM/JunoPkg/ArmJuno.dsc
+++ b/Platform/ARM/JunoPkg/ArmJuno.dsc
@@ -36,11 +36,10 @@ [Defines]
 [LibraryClasses.common]
   ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
   ArmMmuLib|ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf
-  ArmPlatformLib|ArmPlatformPkg/ArmJunoPkg/Library/ArmJunoLib/ArmJunoLib.inf
+  ArmPlatformLib|Platform/ARM/JunoPkg/Library/ArmJunoLib/ArmJunoLib.inf
   ArmSmcLib|ArmPkg/Library/ArmSmcLib/ArmSmcLib.inf
 
-  ArmPlatformSysConfigLib|ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressSysConfigLib/ArmVExpressSysConfigLib.inf
-  NorFlashPlatformLib|ArmPlatformPkg/ArmJunoPkg/Library/NorFlashJunoLib/NorFlashJunoLib.inf
+  NorFlashPlatformLib|Platform/ARM/JunoPkg/Library/NorFlashJunoLib/NorFlashJunoLib.inf
 
   TimerLib|ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf
   CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
@@ -71,7 +70,6 @@ [LibraryClasses.common.UEFI_DRIVER, LibraryClasses.common.UEFI_APPLICATION, Libr
   PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
 
 [BuildOptions]
-  *_*_*_PLATFORM_FLAGS = -I$(WORKSPACE)/ArmPlatformPkg/ArmVExpressPkg/Include -I$(WORKSPACE)/ArmPlatformPkg/ArmJunoPkg/Include
   GCC:*_*_ARM_PLATFORM_FLAGS = -march=armv8-a
 
 ################################################################################
@@ -333,7 +331,7 @@ [Components.common]
   #
   # Juno platform driver
   #
-  ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf
+  Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf
 
   #
   # SMBIOS/DMI
diff --git a/Platform/ARM/JunoPkg/ArmJuno.fdf b/Platform/ARM/JunoPkg/ArmJuno.fdf
index 527e131de5a4..bb78e1fa8589 100644
--- a/Platform/ARM/JunoPkg/ArmJuno.fdf
+++ b/Platform/ARM/JunoPkg/ArmJuno.fdf
@@ -208,7 +208,7 @@ [FV.FvMain]
   #
   # Juno platform driver
   #
-  INF ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf
+  INF Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf
 
   #
   # SMBIOS/DMI
diff --git a/Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/AcpiTables.c b/Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/AcpiTables.c
new file mode 100644
index 000000000000..bf0834643411
--- /dev/null
+++ b/Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/AcpiTables.c
@@ -0,0 +1,78 @@
+/** @file
+
+  This file contains support for ACPI Tables that are generated at boot time.
+
+  Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>
+
+  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 "ArmPlatform.h"
+#include "ArmJunoDxeInternal.h"
+
+#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
+
+/*
+ * Memory Mapped Configuration Space Access Table (MCFG)
+ */
+typedef struct {
+  EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER                        Header;
+  EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE Entry;
+} MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ACCESS_TABLE;
+
+MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ACCESS_TABLE mAcpiMcfgTable = {
+    {
+        ARM_ACPI_HEADER (
+          EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
+          MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ACCESS_TABLE,
+          EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION
+        ),
+        0, // Reserved
+    }, {
+        FixedPcdGet32 (PcdPciConfigurationSpaceBaseAddress),
+        0, // PciSegmentGroupNumber
+        FixedPcdGet32 (PcdPciBusMin),
+        FixedPcdGet32 (PcdPciBusMax),
+        0 // Reserved;
+    }
+};
+
+/**
+ * Callback called when ACPI Protocol is installed
+ */
+VOID
+AcpiPciNotificationEvent (
+  IN  EFI_EVENT                Event,
+  IN  VOID                     *Context
+  )
+{
+  EFI_STATUS                Status;
+  EFI_ACPI_TABLE_PROTOCOL   *AcpiTableProtocol;
+  UINTN                     AcpiTableKey;
+
+  //
+  // Ensure the ACPI protocol is installed
+  //
+  Status = gBS->LocateProtocol (
+                  &gEfiAcpiTableProtocolGuid,
+                  NULL,
+                  (VOID**)&AcpiTableProtocol
+                  );
+  if (EFI_ERROR (Status)) {
+    return;
+  }
+
+  //
+  // Install MCFG Table
+  //
+  AcpiTableKey = 0;
+  Status = AcpiTableProtocol->InstallAcpiTable (AcpiTableProtocol, &mAcpiMcfgTable, sizeof (mAcpiMcfgTable), &AcpiTableKey);
+  ASSERT_EFI_ERROR (Status);
+}
diff --git a/Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.c b/Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.c
new file mode 100644
index 000000000000..18491c737852
--- /dev/null
+++ b/Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.c
@@ -0,0 +1,550 @@
+/** @file
+*
+*  Copyright (c) 2013-2015, 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 "ArmJunoDxeInternal.h"
+#include <ArmPlatform.h>
+
+#include <IndustryStandard/Pci.h>
+#include <Protocol/DevicePathFromText.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/PciRootBridgeIo.h>
+
+#include <Guid/EventGroup.h>
+#include <Guid/GlobalVariable.h>
+
+#include <Library/ArmShellCmdLib.h>
+#include <Library/AcpiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NonDiscoverableDeviceRegistrationLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/IoLib.h>
+#include <Library/PrintLib.h>
+
+
+// This GUID must match the FILE_GUID in ArmPlatformPkg/ArmJunoPkg/AcpiTables/AcpiTables.inf
+STATIC CONST EFI_GUID mJunoAcpiTableFile = { 0xa1dd808e, 0x1e95, 0x4399, { 0xab, 0xc0, 0x65, 0x3c, 0x82, 0xe8, 0x53, 0x0c } };
+
+typedef struct {
+  ACPI_HID_DEVICE_PATH      AcpiDevicePath;
+  PCI_DEVICE_PATH           PciDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  EndDevicePath;
+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
+
+STATIC CONST EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mPciRootComplexDevicePath = {
+    {
+      { ACPI_DEVICE_PATH,
+        ACPI_DP,
+        { (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),
+          (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) }
+      },
+      EISA_PNP_ID (0x0A03),
+      0
+    },
+    {
+      { HARDWARE_DEVICE_PATH,
+        HW_PCI_DP,
+        { (UINT8) (sizeof (PCI_DEVICE_PATH)),
+          (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) }
+      },
+      0,
+      0
+    },
+    {
+      END_DEVICE_PATH_TYPE,
+      END_ENTIRE_DEVICE_PATH_SUBTYPE,
+      { END_DEVICE_PATH_LENGTH, 0 }
+    }
+};
+
+EFI_EVENT mAcpiRegistration = NULL;
+
+/**
+  This function reads PCI ID of the controller.
+
+  @param[in]  PciIo   PCI IO protocol handle
+  @param[in]  PciId   Looking for specified PCI ID Vendor/Device
+**/
+STATIC
+EFI_STATUS
+ReadMarvellYoukonPciId (
+  IN EFI_PCI_IO_PROTOCOL  *PciIo,
+  IN UINT32               PciId
+  )
+{
+  UINT32      DevicePciId;
+  EFI_STATUS  Status;
+
+  Status = PciIo->Pci.Read (
+                        PciIo,
+                        EfiPciIoWidthUint32,
+                        PCI_VENDOR_ID_OFFSET,
+                        1,
+                        &DevicePciId);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (DevicePciId != PciId) {
+    return EFI_NOT_FOUND;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This function searches for Marvell Yukon NIC on the Juno
+  platform and returns PCI IO protocol handle for the controller.
+
+  @param[out]  PciIo   PCI IO protocol handle
+**/
+STATIC
+EFI_STATUS
+GetMarvellYukonPciIoProtocol (
+  OUT EFI_PCI_IO_PROTOCOL  **PciIo
+  )
+{
+  UINTN       HandleCount;
+  EFI_HANDLE  *HandleBuffer;
+  UINTN       HIndex;
+  EFI_STATUS  Status;
+
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiPciIoProtocolGuid,
+                  NULL,
+                  &HandleCount,
+                  &HandleBuffer);
+  if (EFI_ERROR (Status)) {
+    return (Status);
+  }
+
+  for (HIndex = 0; HIndex < HandleCount; ++HIndex) {
+    // If PciIo opened with EFI_OPEN_PROTOCOL_GET_PROTOCOL, the CloseProtocol() is not required
+    Status = gBS->OpenProtocol (
+                    HandleBuffer[HIndex],
+                    &gEfiPciIoProtocolGuid,
+                    (VOID **) PciIo,
+                    NULL,
+                    NULL,
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+    if (EFI_ERROR (Status)) {
+      continue;
+    }
+
+    Status = ReadMarvellYoukonPciId (*PciIo, JUNO_MARVELL_YUKON_ID);
+    if (EFI_ERROR (Status)) {
+      continue;
+    } else {
+      break;
+    }
+  }
+
+  gBS->FreePool (HandleBuffer);
+
+  return Status;
+}
+
+/**
+ This function restore the original controller attributes
+
+   @param[in]   PciIo               PCI IO protocol handle
+   @param[in]   PciAttr             PCI controller attributes.
+   @param[in]   AcpiResDescriptor   ACPI 2.0 resource descriptors for the BAR
+**/
+STATIC
+VOID
+RestorePciDev (
+  IN EFI_PCI_IO_PROTOCOL                *PciIo,
+  IN UINT64                             PciAttr
+  )
+{
+  PciIo->Attributes (
+           PciIo,
+           EfiPciIoAttributeOperationSet,
+           PciAttr,
+           NULL
+           );
+}
+
+/**
+ This function returns PCI MMIO base address for a controller
+
+   @param[in]   PciIo               PCI IO protocol handle
+   @param[out]  PciRegBase          PCI base MMIO address
+**/
+STATIC
+EFI_STATUS
+BarIsDeviceMemory (
+  IN   EFI_PCI_IO_PROTOCOL *PciIo,
+  OUT  UINT32              *PciRegBase
+  )
+{
+  EFI_STATUS                         Status;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *AcpiResDescriptor;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *AcpiCurrentDescriptor;
+
+  // Marvell Yukon's Bar0 provides base memory address for control registers
+  Status = PciIo->GetBarAttributes (PciIo, PCI_BAR_IDX0, NULL, (VOID**)&AcpiResDescriptor);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  AcpiCurrentDescriptor = AcpiResDescriptor;
+
+  // Search for a memory type descriptor
+  while (AcpiCurrentDescriptor->Desc != ACPI_END_TAG_DESCRIPTOR) {
+
+    // Check if Bar is memory type one and fetch a base address
+    if (AcpiCurrentDescriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR &&
+        AcpiCurrentDescriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM &&
+        !(AcpiCurrentDescriptor->SpecificFlag & ACPI_SPECFLAG_PREFETCHABLE)) {
+      *PciRegBase = AcpiCurrentDescriptor->AddrRangeMin;
+      break;
+    } else {
+      Status = EFI_UNSUPPORTED;
+    }
+
+    AcpiCurrentDescriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (AcpiCurrentDescriptor + 1);
+  }
+
+  gBS->FreePool (AcpiResDescriptor);
+
+  return Status;
+}
+
+/**
+ This function provides PCI MMIO base address, old PCI controller attributes.
+
+   @param[in]   PciIo               PCI IO protocol handle
+   @param[out]  PciRegBase          PCI base MMIO address
+   @param[out]  OldPciAttr          Old PCI controller attributes.
+**/
+STATIC
+EFI_STATUS
+InitPciDev (
+  IN EFI_PCI_IO_PROTOCOL                 *PciIo,
+  OUT UINT32                             *PciRegBase,
+  OUT UINT64                             *OldPciAttr
+  )
+{
+  UINT64      AttrSupports;
+  EFI_STATUS  Status;
+
+  // Get controller's current attributes
+  Status = PciIo->Attributes (
+                    PciIo,
+                    EfiPciIoAttributeOperationGet,
+                    0,
+                    OldPciAttr);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  // Fetch supported attributes
+  Status = PciIo->Attributes (
+                    PciIo,
+                    EfiPciIoAttributeOperationSupported,
+                    0,
+                    &AttrSupports);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  // Enable EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_MEMORY and
+  // EFI_PCI_IO_ATTRIBUTE_BUS_MASTER bits in the PCI Config Header
+  AttrSupports &= EFI_PCI_DEVICE_ENABLE;
+  Status = PciIo->Attributes (
+                    PciIo,
+                    EfiPciIoAttributeOperationEnable,
+                    AttrSupports,
+                    NULL);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = BarIsDeviceMemory (PciIo, PciRegBase);
+  if (EFI_ERROR (Status)) {
+    RestorePciDev (PciIo, *OldPciAttr);
+  }
+
+  return Status;
+}
+
+/**
+ This function reads MAC address from IOFPGA and writes it to Marvell Yukon NIC
+
+   @param[in]   PciRegBase   PCI base MMIO address
+**/
+STATIC
+EFI_STATUS
+WriteMacAddress (
+  IN UINT32  PciRegBase
+  )
+{
+  UINT32  MacHigh;
+  UINT32  MacLow;
+
+  // Read MAC address from IOFPGA
+  MacHigh= MmioRead32 (ARM_JUNO_SYS_PCIGBE_H);
+  MacLow = MmioRead32 (ARM_JUNO_SYS_PCIGBE_L);
+
+  // Set software reset control register to protect from deactivation
+  // the config write state
+  MmioWrite16 (PciRegBase + R_CONTROL_STATUS, CS_RESET_CLR);
+
+  // Convert to Marvell MAC Address register format
+  MacHigh = SwapBytes32 ((MacHigh & 0xFFFF) << 16 |
+                         (MacLow & 0xFFFF0000) >> 16);
+  MacLow = SwapBytes32 (MacLow) >> 16;
+
+  // Set MAC Address
+  MmioWrite8 (PciRegBase + R_TST_CTRL_1, TST_CFG_WRITE_ENABLE);
+  MmioWrite32 (PciRegBase + R_MAC, MacHigh);
+  MmioWrite32 (PciRegBase + R_MAC_MAINT, MacHigh);
+  MmioWrite32 (PciRegBase + R_MAC + R_MAC_LOW, MacLow);
+  MmioWrite32 (PciRegBase + R_MAC_MAINT + R_MAC_LOW, MacLow);
+  MmioWrite8 (PciRegBase + R_TST_CTRL_1, TST_CFG_WRITE_DISABLE);
+
+  // Initiate device reset
+  MmioWrite16 (PciRegBase + R_CONTROL_STATUS, CS_RESET_SET);
+  MmioWrite16 (PciRegBase + R_CONTROL_STATUS, CS_RESET_CLR);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  The function reads MAC address from Juno IOFPGA registers and writes it
+  into Marvell Yukon NIC.
+**/
+STATIC
+EFI_STATUS
+ArmJunoSetNicMacAddress ()
+{
+  UINT64                              OldPciAttr;
+  EFI_PCI_IO_PROTOCOL*                PciIo;
+  UINT32                              PciRegBase;
+  EFI_STATUS                          Status;
+
+  Status = GetMarvellYukonPciIoProtocol (&PciIo);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  PciRegBase = 0;
+  Status = InitPciDev (PciIo, &PciRegBase, &OldPciAttr);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = WriteMacAddress (PciRegBase);
+
+  RestorePciDev (PciIo, OldPciAttr);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Notification function of the event defined as belonging to the
+  EFI_END_OF_DXE_EVENT_GROUP_GUID event group that was created in
+  the entry point of the driver.
+
+  This function is called when an event belonging to the
+  EFI_END_OF_DXE_EVENT_GROUP_GUID event group is signalled. Such an
+  event is signalled once at the end of the dispatching of all
+  drivers (end of the so called DXE phase).
+
+  @param[in]  Event    Event declared in the entry point of the driver whose
+                       notification function is being invoked.
+  @param[in]  Context  NULL
+**/
+STATIC
+VOID
+OnEndOfDxe (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL* PciRootComplexDevicePath;
+  EFI_HANDLE                Handle;
+  EFI_STATUS                Status;
+
+  //
+  // PCI Root Complex initialization
+  // At the end of the DXE phase, we should get all the driver dispatched.
+  // Force the PCI Root Complex to be initialized. It allows the OS to skip
+  // this step.
+  //
+  PciRootComplexDevicePath = (EFI_DEVICE_PATH_PROTOCOL*) &mPciRootComplexDevicePath;
+  Status = gBS->LocateDevicePath (&gEfiPciRootBridgeIoProtocolGuid,
+                                  &PciRootComplexDevicePath,
+                                  &Handle);
+
+  Status = gBS->ConnectController (Handle, NULL, PciRootComplexDevicePath, FALSE);
+  ASSERT_EFI_ERROR (Status);
+
+  Status = ArmJunoSetNicMacAddress ();
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "ArmJunoDxe: Failed to set Marvell Yukon NIC MAC address\n"));
+  }
+}
+
+EFI_STATUS
+EFIAPI
+ArmJunoEntryPoint (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS            Status;
+  EFI_PHYSICAL_ADDRESS  HypBase;
+  CHAR16                *TextDevicePath;
+  UINTN                 TextDevicePathSize;
+  VOID                  *Buffer;
+  UINT32                JunoRevision;
+  EFI_EVENT             EndOfDxeEvent;
+
+  //
+  // Register the OHCI and EHCI controllers as non-coherent
+  // non-discoverable devices.
+  //
+  Status = RegisterNonDiscoverableMmioDevice (
+             NonDiscoverableDeviceTypeOhci,
+             NonDiscoverableDeviceDmaTypeNonCoherent,
+             NULL,
+             NULL,
+             1,
+             FixedPcdGet32 (PcdSynopsysUsbOhciBaseAddress),
+             SIZE_64KB
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = RegisterNonDiscoverableMmioDevice (
+             NonDiscoverableDeviceTypeEhci,
+             NonDiscoverableDeviceDmaTypeNonCoherent,
+             NULL,
+             NULL,
+             1,
+             FixedPcdGet32 (PcdSynopsysUsbEhciBaseAddress),
+             SIZE_64KB
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // If a hypervisor has been declared then we need to make sure its region is protected at runtime
+  //
+  // Note: This code is only a workaround for our dummy hypervisor (ArmPkg/Extra/AArch64ToAArch32Shim/)
+  //       that does not set up (yet) the stage 2 translation table to hide its own memory to EL1.
+  //
+  if (FixedPcdGet32 (PcdHypFvSize) != 0) {
+    // Ensure the hypervisor region is strictly contained into a EFI_PAGE_SIZE-aligned region.
+    // The memory must be a multiple of EFI_PAGE_SIZE to ensure we do not reserve more memory than the hypervisor itself.
+    // A UEFI Runtime region size granularity cannot be smaller than EFI_PAGE_SIZE. If the hypervisor size is not rounded
+    // to this size then there is a risk some non-runtime memory could be visible to the OS view.
+    if (((FixedPcdGet32 (PcdHypFvSize) & EFI_PAGE_MASK) == 0) && ((FixedPcdGet32 (PcdHypFvBaseAddress) & EFI_PAGE_MASK) == 0)) {
+      // The memory needs to be declared because the DXE core marked it as reserved and removed it from the memory space
+      // as it contains the Firmware.
+      Status = gDS->AddMemorySpace (
+          EfiGcdMemoryTypeSystemMemory,
+          FixedPcdGet32 (PcdHypFvBaseAddress), FixedPcdGet32 (PcdHypFvSize),
+          EFI_MEMORY_WB | EFI_MEMORY_RUNTIME
+          );
+      if (!EFI_ERROR (Status)) {
+        // We allocate the memory to ensure it is marked as runtime memory
+        HypBase = FixedPcdGet32 (PcdHypFvBaseAddress);
+        Status = gBS->AllocatePages (AllocateAddress, EfiRuntimeServicesCode,
+                                     EFI_SIZE_TO_PAGES (FixedPcdGet32 (PcdHypFvSize)), &HypBase);
+      }
+    } else {
+      // The hypervisor must be contained into a EFI_PAGE_SIZE-aligned region and its size must also be aligned
+      // on a EFI_PAGE_SIZE boundary (ie: 4KB).
+      Status = EFI_UNSUPPORTED;
+      ASSERT_EFI_ERROR (Status);
+    }
+
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  // Install dynamic Shell command to run baremetal binaries.
+  Status = ShellDynCmdRunAxfInstall (ImageHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "ArmJunoDxe: Failed to install ShellDynCmdRunAxf\n"));
+  }
+
+  GetJunoRevision(JunoRevision);
+
+  //
+  // Try to install the ACPI Tables
+  //
+  Status = LocateAndInstallAcpiFromFv (&mJunoAcpiTableFile);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Setup R1/R2 options if not already done.
+  //
+  if (JunoRevision != JUNO_REVISION_R0) {
+    // Enable PCI enumeration
+    PcdSetBool (PcdPciDisableBusEnumeration, FALSE);
+
+    //
+    // Create an event belonging to the "gEfiEndOfDxeEventGroupGuid" group.
+    // The "OnEndOfDxe()" function is declared as the call back function.
+    // It will be called at the end of the DXE phase when an event of the
+    // same group is signalled to inform about the end of the DXE phase.
+    // Install the INSTALL_FDT_PROTOCOL protocol.
+    //
+    Status = gBS->CreateEventEx (
+                    EVT_NOTIFY_SIGNAL,
+                    TPL_CALLBACK,
+                    OnEndOfDxe,
+                    NULL,
+                    &gEfiEndOfDxeEventGroupGuid,
+                    &EndOfDxeEvent
+                    );
+
+    // Declare the related ACPI Tables
+    EfiCreateProtocolNotifyEvent (
+        &gEfiAcpiTableProtocolGuid,
+        TPL_CALLBACK,
+        AcpiPciNotificationEvent,
+        NULL,
+        &mAcpiRegistration
+        );
+  }
+
+  //
+  // Set up the device path to the FDT.
+  //
+  TextDevicePath = (CHAR16*)FixedPcdGetPtr (PcdJunoFdtDevicePath);
+  if (TextDevicePath != NULL) {
+    TextDevicePathSize = StrSize (TextDevicePath);
+    Buffer = PcdSetPtr (PcdFdtDevicePaths, &TextDevicePathSize, TextDevicePath);
+    Status = (Buffer != NULL) ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL;
+  } else {
+    Status = EFI_NOT_FOUND;
+  }
+
+  if (EFI_ERROR (Status)) {
+    DEBUG (
+      (EFI_D_ERROR,
+      "ArmJunoDxe: Setting of FDT device path in PcdFdtDevicePaths failed - %r\n", Status)
+      );
+    return Status;
+  }
+
+  return Status;
+}
diff --git a/Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf b/Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf
new file mode 100644
index 000000000000..b215a3bc882d
--- /dev/null
+++ b/Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf
@@ -0,0 +1,88 @@
+#
+#  Copyright (c) 2013-2015, 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.
+#
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = ArmJunoDxe
+  FILE_GUID                      = 1484ebe8-2681-45f1-a2e5-12ecad893b62
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = ArmJunoEntryPoint
+
+[Sources.common]
+  AcpiTables.c
+  ArmJunoDxe.c
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  Platform/ARM/JunoPkg/ArmJuno.dec
+
+[LibraryClasses]
+  AcpiLib
+  ArmLib
+  ArmShellCmdRunAxfLib
+  BaseMemoryLib
+  DebugLib
+  DxeServicesTableLib
+  IoLib
+  NonDiscoverableDeviceRegistrationLib
+  PcdLib
+  PrintLib
+  SerialPortLib
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  UefiLib
+  UefiDriverEntryPoint
+
+[Guids]
+  gEfiEndOfDxeEventGroupGuid
+  gEfiFileInfoGuid
+
+[Protocols]
+  gEfiBlockIoProtocolGuid
+  gEfiDevicePathFromTextProtocolGuid
+  gEfiPciIoProtocolGuid
+  gEfiPciRootBridgeIoProtocolGuid
+  gEfiSimpleFileSystemProtocolGuid
+  gEfiAcpiTableProtocolGuid
+
+[FixedPcd]
+  gArmTokenSpaceGuid.PcdSystemMemoryBase
+  gArmTokenSpaceGuid.PcdSystemMemorySize
+
+  gArmTokenSpaceGuid.PcdHypFvBaseAddress
+  gArmTokenSpaceGuid.PcdHypFvSize
+
+  gArmJunoTokenSpaceGuid.PcdSynopsysUsbEhciBaseAddress
+  gArmJunoTokenSpaceGuid.PcdSynopsysUsbOhciBaseAddress
+
+  gArmJunoTokenSpaceGuid.PcdJunoFdtDevicePath
+
+  gArmPlatformTokenSpaceGuid.PcdDefaultBootDevicePath
+  gArmPlatformTokenSpaceGuid.PcdDefaultBootArgument
+
+  # PCI Root complex specific PCDs
+  gArmJunoTokenSpaceGuid.PcdPciConfigurationSpaceBaseAddress
+  gArmTokenSpaceGuid.PcdPciBusMin
+  gArmTokenSpaceGuid.PcdPciBusMax
+
+[Pcd]
+  gEmbeddedTokenSpaceGuid.PcdFdtDevicePaths
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration
+
+[Depex]
+  # We depend on these protocols to create the default boot entries
+  gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid
diff --git a/Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxeInternal.h b/Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxeInternal.h
new file mode 100644
index 000000000000..5d2b68fabd12
--- /dev/null
+++ b/Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxeInternal.h
@@ -0,0 +1,54 @@
+/** @file
+*
+*  Copyright (c) 2013-2015, 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.
+*
+**/
+
+#ifndef __ARM_JUNO_DXE_INTERNAL_H__
+#define __ARM_JUNO_DXE_INTERNAL_H__
+
+#include <Uefi.h>
+
+#include <Library/BaseLib.h>
+#include <Library/ArmLib.h>
+#include <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include <Protocol/AcpiTable.h>
+
+#include <IndustryStandard/Acpi.h>
+
+#define ACPI_SPECFLAG_PREFETCHABLE    0x06
+#define JUNO_MARVELL_YUKON_ID         0x438011AB /* Juno Marvell PCI Dev ID */
+#define TST_CFG_WRITE_ENABLE          0x02       /* Enable Config Write */
+#define TST_CFG_WRITE_DISABLE         0x00       /* Disable Config Write */
+#define CS_RESET_CLR                  0x02       /* SW Reset Clear */
+#define CS_RESET_SET                  0x00       /* SW Reset Set */
+#define R_CONTROL_STATUS              0x0004     /* Control/Status Register */
+#define R_MAC                         0x0100     /* MAC Address */
+#define R_MAC_MAINT                   0x0110     /* MAC Address Maintenance */
+#define R_MAC_LOW                     0x04       /* MAC Address Low Register Offset */
+#define R_TST_CTRL_1                  0x0158     /* Test Control Register 1 */
+
+
+/**
+ * Callback called when ACPI Protocol is installed
+ */
+VOID
+AcpiPciNotificationEvent (
+  IN  EFI_EVENT                Event,
+  IN  VOID                     *Context
+  );
+
+#endif // __ARM_JUNO_DXE_INTERNAL_H__
diff --git a/Platform/ARM/JunoPkg/Include/ArmPlatform.h b/Platform/ARM/JunoPkg/Include/ArmPlatform.h
new file mode 100644
index 000000000000..399fd952791f
--- /dev/null
+++ b/Platform/ARM/JunoPkg/Include/ArmPlatform.h
@@ -0,0 +1,180 @@
+/** @file
+*
+*  Copyright (c) 2013-2017, 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.
+*
+**/
+
+#ifndef __ARM_JUNO_H__
+#define __ARM_JUNO_H__
+
+//#include <VExpressMotherBoard.h>
+
+/***********************************************************************************
+// Platform Memory Map
+************************************************************************************/
+
+// Motherboard Peripheral and On-chip peripheral
+#define ARM_VE_BOARD_PERIPH_BASE              0x1C010000
+#define ARM_VE_BOARD_SYS_ID                   0x0000
+#define ARM_VE_BOARD_SYS_PCIE_GBE_L           0x0074
+#define ARM_VE_BOARD_SYS_PCIE_GBE_H           0x0078
+
+#define ARM_VE_BOARD_SYS_ID_REV(word)         ((word >> 28) & 0xff)
+
+// NOR Flash 0
+#define ARM_VE_SMB_NOR0_BASE                  0x08000000
+#define ARM_VE_SMB_NOR0_SZ                    SIZE_64MB
+
+// Off-Chip peripherals (USB, Ethernet, VRAM)
+#define ARM_VE_SMB_PERIPH_BASE                0x18000000
+#define ARM_VE_SMB_PERIPH_SZ                  (SIZE_64MB + SIZE_2MB)
+
+// On-Chip non-secure ROM
+#define ARM_JUNO_NON_SECURE_ROM_BASE          0x1F000000
+#define ARM_JUNO_NON_SECURE_ROM_SZ            SIZE_16MB
+
+// On-Chip Peripherals
+#define ARM_JUNO_PERIPHERALS_BASE             0x20000000
+#define ARM_JUNO_PERIPHERALS_SZ               0x0E000000
+
+// PCIe MSI address window
+#define ARM_JUNO_GIV2M_MSI_BASE               0x2c1c0000
+#define ARM_JUNO_GIV2M_MSI_SZ                 SIZE_256KB
+
+// PCIe MSI to SPI mapping range
+#define ARM_JUNO_GIV2M_MSI_SPI_BASE           224
+#define ARM_JUNO_GIV2M_MSI_SPI_COUNT          127 //TRM says last SPI is 351, 351-224=127
+
+// On-Chip non-secure SRAM
+#define ARM_JUNO_NON_SECURE_SRAM_BASE         0x2E000000
+#define ARM_JUNO_NON_SECURE_SRAM_SZ           SIZE_16MB
+
+// SOC peripherals (HDLCD, UART, I2C, I2S, USB, SMC-PL354, etc)
+#define ARM_JUNO_SOC_PERIPHERALS_BASE         0x7FF50000
+#define ARM_JUNO_SOC_PERIPHERALS_SZ           (SIZE_64KB * 9)
+
+// 6GB of DRAM from the 64bit address space
+#define ARM_JUNO_EXTRA_SYSTEM_MEMORY_BASE     0x0880000000
+#define ARM_JUNO_EXTRA_SYSTEM_MEMORY_SZ       (SIZE_2GB + SIZE_4GB)
+
+//
+// ACPI table information used to initialize tables.
+//
+#define EFI_ACPI_ARM_OEM_ID           'A','R','M','L','T','D'   // OEMID 6 bytes long
+#define EFI_ACPI_ARM_OEM_TABLE_ID     SIGNATURE_64('A','R','M','-','J','U','N','O') // OEM table id 8 bytes long
+#define EFI_ACPI_ARM_OEM_REVISION     0x20140727
+#define EFI_ACPI_ARM_CREATOR_ID       SIGNATURE_32('A','R','M',' ')
+#define EFI_ACPI_ARM_CREATOR_REVISION 0x00000099
+
+// A macro to initialise the common header part of EFI ACPI tables as defined by
+// EFI_ACPI_DESCRIPTION_HEADER structure.
+#define ARM_ACPI_HEADER(Signature, Type, Revision) {              \
+    Signature,                      /* UINT32  Signature */       \
+    sizeof (Type),                  /* UINT32  Length */          \
+    Revision,                       /* UINT8   Revision */        \
+    0,                              /* UINT8   Checksum */        \
+    { EFI_ACPI_ARM_OEM_ID },        /* UINT8   OemId[6] */        \
+    EFI_ACPI_ARM_OEM_TABLE_ID,      /* UINT64  OemTableId */      \
+    EFI_ACPI_ARM_OEM_REVISION,      /* UINT32  OemRevision */     \
+    EFI_ACPI_ARM_CREATOR_ID,        /* UINT32  CreatorId */       \
+    EFI_ACPI_ARM_CREATOR_REVISION   /* UINT32  CreatorRevision */ \
+  }
+
+//
+// Hardware platform identifiers
+//
+#define JUNO_REVISION_PROTOTYPE 0
+#define JUNO_REVISION_R0        1
+#define JUNO_REVISION_R1        2
+#define JUNO_REVISION_R2        3
+#define JUNO_REVISION_UKNOWN    0xFF
+
+//
+// We detect whether we are running on a Juno r0, r1 or r2
+// board at runtime by checking the value of board SYS_ID
+//
+#define GetJunoRevision(JunoRevision)                                  \
+{                                                                      \
+  UINT32    SysId;                                                     \
+  SysId = MmioRead32 (ARM_VE_BOARD_PERIPH_BASE+ARM_VE_BOARD_SYS_ID);   \
+  JunoRevision = ARM_VE_BOARD_SYS_ID_REV( SysId );                     \
+}
+
+
+// Define if the exported ACPI Tables are based on ACPI 5.0 spec or latest
+//#define ARM_JUNO_ACPI_5_0
+
+//
+// Address of the system registers that contain the MAC address
+// assigned to the PCI Gigabyte Ethernet device.
+//
+
+#define ARM_JUNO_SYS_PCIGBE_L  (ARM_VE_BOARD_PERIPH_BASE + ARM_VE_BOARD_SYS_PCIE_GBE_L)
+#define ARM_JUNO_SYS_PCIGBE_H  (ARM_VE_BOARD_PERIPH_BASE + ARM_VE_BOARD_SYS_PCIE_GBE_H)
+
+/***********************************************************************************
+// Motherboard memory-mapped peripherals
+************************************************************************************/
+
+// Define MotherBoard SYS flags offsets (from ARM_VE_BOARD_PERIPH_BASE)
+#define ARM_VE_SYS_ID_REG                   (ARM_VE_BOARD_PERIPH_BASE + 0x00000)
+#define ARM_VE_SYS_SW_REG                   (ARM_VE_BOARD_PERIPH_BASE + 0x00004)
+#define ARM_VE_SYS_LED_REG                  (ARM_VE_BOARD_PERIPH_BASE + 0x00008)
+#define ARM_VE_SYS_FLAGS_REG                (ARM_VE_BOARD_PERIPH_BASE + 0x00030)
+#define ARM_VE_SYS_FLAGS_SET_REG            (ARM_VE_BOARD_PERIPH_BASE + 0x00030)
+#define ARM_VE_SYS_FLAGS_CLR_REG            (ARM_VE_BOARD_PERIPH_BASE + 0x00034)
+#define ARM_VE_SYS_FLAGS_NV_REG             (ARM_VE_BOARD_PERIPH_BASE + 0x00038)
+#define ARM_VE_SYS_FLAGS_NV_SET_REG         (ARM_VE_BOARD_PERIPH_BASE + 0x00038)
+#define ARM_VE_SYS_FLAGS_NV_CLR_REG         (ARM_VE_BOARD_PERIPH_BASE + 0x0003C)
+#define ARM_VE_SYS_FLASH                    (ARM_VE_BOARD_PERIPH_BASE + 0x0004C)
+#define ARM_VE_SYS_CFGSWR_REG               (ARM_VE_BOARD_PERIPH_BASE + 0x00058)
+#define ARM_VE_SYS_MISC                     (ARM_VE_BOARD_PERIPH_BASE + 0x00060)
+#define ARM_VE_SYS_PROCID0_REG              (ARM_VE_BOARD_PERIPH_BASE + 0x00084)
+#define ARM_VE_SYS_PROCID1_REG              (ARM_VE_BOARD_PERIPH_BASE + 0x00088)
+#define ARM_VE_SYS_CFGDATA_REG              (ARM_VE_BOARD_PERIPH_BASE + 0x000A0)
+#define ARM_VE_SYS_CFGCTRL_REG              (ARM_VE_BOARD_PERIPH_BASE + 0x000A4)
+#define ARM_VE_SYS_CFGSTAT_REG              (ARM_VE_BOARD_PERIPH_BASE + 0x000A8)
+
+//
+// Sites where the peripheral is fitted
+//
+#define ARM_VE_UNSUPPORTED                        ~0
+#define ARM_VE_MOTHERBOARD_SITE                   0
+#define ARM_VE_DAUGHTERBOARD_1_SITE               1
+#define ARM_VE_DAUGHTERBOARD_2_SITE               2
+
+#define VIRTUAL_SYS_CFG(site,func)                (((site) << 24) | (func))
+
+//
+// System Configuration Control Functions
+//
+#define SYS_CFG_OSC           1
+#define SYS_CFG_VOLT          2
+#define SYS_CFG_AMP           3
+#define SYS_CFG_TEMP          4
+#define SYS_CFG_RESET         5
+#define SYS_CFG_SCC           6
+#define SYS_CFG_MUXFPGA       7
+#define SYS_CFG_SHUTDOWN      8
+#define SYS_CFG_REBOOT        9
+#define SYS_CFG_DVIMODE       11
+#define SYS_CFG_POWER         12
+// Oscillator for Site 1
+#define SYS_CFG_OSC_SITE1     VIRTUAL_SYS_CFG(ARM_VE_DAUGHTERBOARD_1_SITE, \
+                                              SYS_CFG_OSC)
+// Oscillator for Site 2
+#define SYS_CFG_OSC_SITE2     VIRTUAL_SYS_CFG(ARM_VE_DAUGHTERBOARD_2_SITE, \
+                                              SYS_CFG_OSC)
+// Can not access the battery backed-up hardware clock on the
+// Versatile Express motherboard
+#define SYS_CFG_RTC           VIRTUAL_SYS_CFG(ARM_VE_UNSUPPORTED,1)
+
+#endif
diff --git a/Platform/ARM/JunoPkg/Library/ArmJunoLib/AArch64/ArmJunoHelper.S b/Platform/ARM/JunoPkg/Library/ArmJunoLib/AArch64/ArmJunoHelper.S
new file mode 100644
index 000000000000..4bdf08d1a98a
--- /dev/null
+++ b/Platform/ARM/JunoPkg/Library/ArmJunoLib/AArch64/ArmJunoHelper.S
@@ -0,0 +1,58 @@
+/** @file
+*
+*  Copyright (c) 2013-2014, 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 <AsmMacroIoLibV8.h>
+#include <Library/ArmLib.h>
+
+//UINTN
+//ArmPlatformGetCorePosition (
+//  IN UINTN MpId
+//  );
+// With this function: CorePos = (ClusterId * 2) + CoreId
+ASM_FUNC(ArmPlatformGetCorePosition)
+  and   x1, x0, #ARM_CORE_MASK
+  and   x0, x0, #ARM_CLUSTER_MASK
+  add   x0, x1, x0, LSR #7
+  ret
+
+//UINTN
+//ArmPlatformGetPrimaryCoreMpId (
+//  VOID
+//  );
+ASM_FUNC(ArmPlatformGetPrimaryCoreMpId)
+  ldr   w0, PrimaryCoreMpid
+  ret
+
+//UINTN
+//ArmPlatformIsPrimaryCore (
+//  IN UINTN MpId
+//  );
+ASM_FUNC(ArmPlatformIsPrimaryCore)
+  MOV32 (w1, FixedPcdGet32 (PcdArmPrimaryCoreMask))
+  and   x0, x0, x1
+
+  ldr   w1, PrimaryCoreMpid
+
+  cmp   w0, w1
+  cset  x0, eq
+  ret
+
+ASM_FUNC(ArmPlatformPeiBootAction)
+  // The trusted firmware passes the primary CPU MPID through x0 register.
+  // Save it in a variable.
+  adr  x1, PrimaryCoreMpid
+  str  w0, [x1]
+  ret
+
+PrimaryCoreMpid:  .word    0x0
diff --git a/Platform/ARM/JunoPkg/Library/ArmJunoLib/Arm/ArmJunoHelper.S b/Platform/ARM/JunoPkg/Library/ArmJunoLib/Arm/ArmJunoHelper.S
new file mode 100644
index 000000000000..a7e904eac697
--- /dev/null
+++ b/Platform/ARM/JunoPkg/Library/ArmJunoLib/Arm/ArmJunoHelper.S
@@ -0,0 +1,91 @@
+/** @file
+*
+*  Copyright (c) 2013-2014, 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 <AsmMacroIoLib.h>
+#include <Library/ArmLib.h>
+
+//
+// Return the core position from the value of its MpId register
+//
+// This function returns the core position from the position 0 in the processor.
+// This function might be called from assembler before any stack is set.
+//
+// @return   Return the core position
+//
+//UINTN
+//ArmPlatformGetCorePosition (
+//  IN UINTN MpId
+//  );
+// With this function: CorePos = (ClusterId * 2) + CoreId
+ASM_FUNC(ArmPlatformGetCorePosition)
+  and   r1, r0, #ARM_CORE_MASK
+  and   r0, r0, #ARM_CLUSTER_MASK
+  add   r0, r1, r0, LSR #7
+  bx    lr
+
+//
+// Return the MpId of the primary core
+//
+// This function returns the MpId of the primary core.
+// This function might be called from assembler before any stack is set.
+//
+// @return   Return the MpId of the primary core
+//
+//UINTN
+//ArmPlatformGetPrimaryCoreMpId (
+//  VOID
+//  );
+ASM_FUNC(ArmPlatformGetPrimaryCoreMpId)
+  LDRL  (r0, PrimaryCoreMpid)
+  bx    lr
+
+//
+// Return a non-zero value if the callee is the primary core
+//
+// This function returns a non-zero value if the callee is the primary core.
+// The primary core is the core responsible to initialize the hardware and run UEFI.
+// This function might be called from assembler before any stack is set.
+//
+//  @return   Return a non-zero value if the callee is the primary core.
+//
+//UINTN
+//ArmPlatformIsPrimaryCore (
+//  IN UINTN MpId
+//  );
+ASM_FUNC(ArmPlatformIsPrimaryCore)
+  MOV32 (r1, FixedPcdGet32 (PcdArmPrimaryCoreMask))
+  and   r0, r0, r1
+
+  LDRL  (r1, PrimaryCoreMpid)
+
+  cmp   r0, r1
+  moveq r0, #1
+  movne r0, #0
+  bx    lr
+
+//
+// First platform specific function to be called in the PEI phase
+//
+// This function is actually the first function called by the PrePi
+// or PrePeiCore modules. It allows to retrieve arguments passed to
+// the UEFI firmware through the CPU registers.
+//
+ASM_FUNC(ArmPlatformPeiBootAction)
+  // The trusted firmware passes the primary CPU MPID through r0 register.
+  // Save it in a variable.
+  adr  r1, PrimaryCoreMpid
+  str  r0, [r1]
+  bx   lr
+
+PrimaryCoreMpid:  .word    0x0
diff --git a/Platform/ARM/JunoPkg/Library/ArmJunoLib/ArmJuno.c b/Platform/ARM/JunoPkg/Library/ArmJunoLib/ArmJuno.c
new file mode 100644
index 000000000000..4a57ec5517ec
--- /dev/null
+++ b/Platform/ARM/JunoPkg/Library/ArmJunoLib/ArmJuno.c
@@ -0,0 +1,193 @@
+/** @file
+*
+*  Copyright (c) 2013-2016, 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 <Drivers/PL011Uart.h>
+
+#include <Library/IoLib.h>
+#include <Library/ArmPlatformLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+
+#include <Ppi/ArmMpCoreInfo.h>
+
+#include <ArmPlatform.h>
+
+ARM_CORE_INFO mJunoInfoTable[] = {
+  {
+    // Cluster 0, Core 0
+    0x0, 0x0,
+
+    // MP Core MailBox Set/Get/Clear Addresses and Clear Value
+    (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_REG,
+    (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_SET_REG,
+    (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_CLR_REG,
+    (UINT64)0xFFFFFFFF
+  },
+  {
+    // Cluster 0, Core 1
+    0x0, 0x1,
+
+    // MP Core MailBox Set/Get/Clear Addresses and Clear Value
+    (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_REG,
+    (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_SET_REG,
+    (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_CLR_REG,
+    (UINT64)0xFFFFFFFF
+  },
+  {
+    // Cluster 1, Core 0
+    0x1, 0x0,
+
+    // MP Core MailBox Set/Get/Clear Addresses and Clear Value
+    (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_REG,
+    (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_SET_REG,
+    (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_CLR_REG,
+    (UINT64)0xFFFFFFFF
+  },
+  {
+    // Cluster 1, Core 1
+    0x1, 0x1,
+
+    // MP Core MailBox Set/Get/Clear Addresses and Clear Value
+    (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_REG,
+    (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_SET_REG,
+    (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_CLR_REG,
+    (UINT64)0xFFFFFFFF
+  },
+  {
+    // Cluster 1, Core 2
+    0x1, 0x2,
+
+    // MP Core MailBox Set/Get/Clear Addresses and Clear Value
+    (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_REG,
+    (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_SET_REG,
+    (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_CLR_REG,
+    (UINT64)0xFFFFFFFF
+  },
+  {
+    // Cluster 1, Core 3
+    0x1, 0x3,
+
+    // MP Core MailBox Set/Get/Clear Addresses and Clear Value
+    (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_REG,
+    (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_SET_REG,
+    (EFI_PHYSICAL_ADDRESS)ARM_VE_SYS_FLAGS_CLR_REG,
+    (UINT64)0xFFFFFFFF
+  }
+};
+
+/**
+  Return the current Boot Mode
+
+  This function returns the boot reason on the platform
+
+  @return   Return the current Boot Mode of the platform
+
+**/
+EFI_BOOT_MODE
+ArmPlatformGetBootMode (
+  VOID
+  )
+{
+  return BOOT_WITH_FULL_CONFIGURATION;
+}
+
+/**
+  Initialize controllers that must setup in the normal world
+
+  This function is called by the ArmPlatformPkg/Pei or ArmPlatformPkg/Pei/PlatformPeim
+  in the PEI phase.
+
+**/
+RETURN_STATUS
+ArmPlatformInitialize (
+  IN  UINTN                     MpId
+  )
+{
+  RETURN_STATUS       Status;
+  UINT64              BaudRate;
+  UINT32              ReceiveFifoDepth;
+  EFI_PARITY_TYPE     Parity;
+  UINT8               DataBits;
+  EFI_STOP_BITS_TYPE  StopBits;
+
+  Status = RETURN_SUCCESS;
+
+  //
+  // Initialize the Serial Debug UART
+  //
+  if (FixedPcdGet64 (PcdSerialDbgRegisterBase)) {
+    ReceiveFifoDepth = 0; // Use the default value for FIFO depth
+    Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity);
+    DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);
+    StopBits = (EFI_STOP_BITS_TYPE)FixedPcdGet8 (PcdUartDefaultStopBits);
+
+    BaudRate = (UINTN)FixedPcdGet64 (PcdSerialDbgUartBaudRate);
+    Status = PL011UartInitializePort (
+               (UINTN)FixedPcdGet64 (PcdSerialDbgRegisterBase),
+               FixedPcdGet32 (PcdSerialDbgUartClkInHz),
+               &BaudRate,
+               &ReceiveFifoDepth,
+               &Parity,
+               &DataBits,
+               &StopBits
+               );
+  }
+
+  return Status;
+}
+
+/**
+  Initialize the system (or sometimes called permanent) memory
+
+  This memory is generally represented by the DRAM.
+
+**/
+VOID
+ArmPlatformInitializeSystemMemory (
+  VOID
+  )
+{
+}
+
+EFI_STATUS
+PrePeiCoreGetMpCoreInfo (
+  OUT UINTN                   *CoreCount,
+  OUT ARM_CORE_INFO           **ArmCoreTable
+  )
+{
+  // Only support one cluster
+  *CoreCount    = sizeof(mJunoInfoTable) / sizeof(ARM_CORE_INFO);
+  *ArmCoreTable = mJunoInfoTable;
+  return EFI_SUCCESS;
+}
+
+ARM_MP_CORE_INFO_PPI mMpCoreInfoPpi = { PrePeiCoreGetMpCoreInfo };
+
+EFI_PEI_PPI_DESCRIPTOR      gPlatformPpiTable[] = {
+  {
+    EFI_PEI_PPI_DESCRIPTOR_PPI,
+    &gArmMpCoreInfoPpiGuid,
+    &mMpCoreInfoPpi
+  }
+};
+
+VOID
+ArmPlatformGetPlatformPpiList (
+  OUT UINTN                   *PpiListSize,
+  OUT EFI_PEI_PPI_DESCRIPTOR  **PpiList
+  )
+{
+  *PpiListSize = sizeof(gPlatformPpiTable);
+  *PpiList = gPlatformPpiTable;
+}
diff --git a/Platform/ARM/JunoPkg/Library/ArmJunoLib/ArmJunoLib.inf b/Platform/ARM/JunoPkg/Library/ArmJunoLib/ArmJunoLib.inf
new file mode 100644
index 000000000000..2dd384daba3d
--- /dev/null
+++ b/Platform/ARM/JunoPkg/Library/ArmJunoLib/ArmJunoLib.inf
@@ -0,0 +1,80 @@
+#
+#  Copyright (c) 2013-2016, 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.
+#
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = ArmJunoLib
+  FILE_GUID                      = 87c525cd-e1a2-469e-994c-c28cd0c7bd0d
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = ArmPlatformLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  Platform/ARM/JunoPkg/ArmJuno.dec
+
+[LibraryClasses]
+  IoLib
+  ArmLib
+  HobLib
+  MemoryAllocationLib
+  SerialPortLib
+
+[Sources.common]
+  ArmJuno.c
+  ArmJunoMem.c
+
+[Sources.AARCH64]
+  AArch64/ArmJunoHelper.S
+
+[Sources.ARM]
+  Arm/ArmJunoHelper.S     | GCC
+
+[FeaturePcd]
+  gEmbeddedTokenSpaceGuid.PcdCacheEnable
+
+[FixedPcd]
+  gArmTokenSpaceGuid.PcdSystemMemoryBase
+  gArmTokenSpaceGuid.PcdSystemMemorySize
+  gArmTokenSpaceGuid.PcdFvBaseAddress
+
+  gArmTokenSpaceGuid.PcdArmPrimaryCoreMask
+
+  gArmJunoTokenSpaceGuid.PcdPcieControlBaseAddress
+  gArmJunoTokenSpaceGuid.PcdPciConfigurationSpaceBaseAddress
+  gArmJunoTokenSpaceGuid.PcdPciConfigurationSpaceSize
+
+
+  #
+  # PL011 Serial Debug UART
+  #
+  gArmPlatformTokenSpaceGuid.PcdSerialDbgRegisterBase
+  gArmPlatformTokenSpaceGuid.PcdSerialDbgUartBaudRate
+  gArmPlatformTokenSpaceGuid.PcdSerialDbgUartClkInHz
+
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
+
+[Pcd]
+  gArmTokenSpaceGuid.PcdPciMmio32Base
+  gArmTokenSpaceGuid.PcdPciMmio32Size
+  gArmTokenSpaceGuid.PcdPciMmio64Base
+  gArmTokenSpaceGuid.PcdPciMmio64Size
+
+[Ppis]
+  gArmMpCoreInfoPpiGuid
diff --git a/Platform/ARM/JunoPkg/Library/ArmJunoLib/ArmJunoMem.c b/Platform/ARM/JunoPkg/Library/ArmJunoLib/ArmJunoMem.c
new file mode 100644
index 000000000000..aa8d7d9c3b0d
--- /dev/null
+++ b/Platform/ARM/JunoPkg/Library/ArmJunoLib/ArmJunoMem.c
@@ -0,0 +1,173 @@
+/** @file
+*
+*  Copyright (c) 2013-2015, 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 <Library/ArmPlatformLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <ArmPlatform.h>
+
+// The total number of descriptors, including the final "end-of-table" descriptor.
+#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS 16
+
+// DDR attributes
+#define DDR_ATTRIBUTES_CACHED           ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK
+#define DDR_ATTRIBUTES_UNCACHED         ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED
+
+/**
+  Return the Virtual Memory Map of your platform
+
+  This Virtual Memory Map is used by MemoryInitPei Module to initialize the MMU on your platform.
+
+  @param[out]   VirtualMemoryMap    Array of ARM_MEMORY_REGION_DESCRIPTOR describing a Physical-to-
+                                    Virtual Memory mapping. This array must be ended by a zero-filled
+                                    entry
+
+**/
+VOID
+ArmPlatformGetVirtualMemoryMap (
+  IN ARM_MEMORY_REGION_DESCRIPTOR** VirtualMemoryMap
+  )
+{
+  ARM_MEMORY_REGION_ATTRIBUTES  CacheAttributes;
+  UINTN                         Index = 0;
+  ARM_MEMORY_REGION_DESCRIPTOR  *VirtualMemoryTable;
+  EFI_RESOURCE_ATTRIBUTE_TYPE   ResourceAttributes;
+
+  ASSERT (VirtualMemoryMap != NULL);
+
+  //
+  // Declared the additional 6GB of memory
+  //
+  ResourceAttributes =
+      EFI_RESOURCE_ATTRIBUTE_PRESENT |
+      EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+      EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+      EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+      EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
+      EFI_RESOURCE_ATTRIBUTE_TESTED;
+
+  BuildResourceDescriptorHob (
+    EFI_RESOURCE_SYSTEM_MEMORY,
+    ResourceAttributes,
+    ARM_JUNO_EXTRA_SYSTEM_MEMORY_BASE,
+    ARM_JUNO_EXTRA_SYSTEM_MEMORY_SZ);
+
+  VirtualMemoryTable = (ARM_MEMORY_REGION_DESCRIPTOR*)AllocatePages(EFI_SIZE_TO_PAGES (sizeof(ARM_MEMORY_REGION_DESCRIPTOR) * MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS));
+  if (VirtualMemoryTable == NULL) {
+      return;
+  }
+
+  if (FeaturePcdGet(PcdCacheEnable) == TRUE) {
+      CacheAttributes = DDR_ATTRIBUTES_CACHED;
+  } else {
+      CacheAttributes = DDR_ATTRIBUTES_UNCACHED;
+  }
+
+  // SMB CS0 - NOR0 Flash
+  VirtualMemoryTable[Index].PhysicalBase    = ARM_VE_SMB_NOR0_BASE;
+  VirtualMemoryTable[Index].VirtualBase     = ARM_VE_SMB_NOR0_BASE;
+  VirtualMemoryTable[Index].Length          = SIZE_256KB * 255;
+  VirtualMemoryTable[Index].Attributes      = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+  // Environment Variables region
+  VirtualMemoryTable[++Index].PhysicalBase  = ARM_VE_SMB_NOR0_BASE + (SIZE_256KB * 255);
+  VirtualMemoryTable[Index].VirtualBase     = ARM_VE_SMB_NOR0_BASE + (SIZE_256KB * 255);
+  VirtualMemoryTable[Index].Length          = SIZE_64KB * 4;
+  VirtualMemoryTable[Index].Attributes      = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+
+  // SMB CS2 & CS3 - Off-chip (motherboard) peripherals
+  VirtualMemoryTable[++Index].PhysicalBase  = ARM_VE_SMB_PERIPH_BASE;
+  VirtualMemoryTable[Index].VirtualBase     = ARM_VE_SMB_PERIPH_BASE;
+  VirtualMemoryTable[Index].Length          = ARM_VE_SMB_PERIPH_SZ;
+  VirtualMemoryTable[Index].Attributes      = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+
+  // Juno OnChip non-secure ROM
+  VirtualMemoryTable[++Index].PhysicalBase  = ARM_JUNO_NON_SECURE_ROM_BASE;
+  VirtualMemoryTable[Index].VirtualBase     = ARM_JUNO_NON_SECURE_ROM_BASE;
+  VirtualMemoryTable[Index].Length          = ARM_JUNO_NON_SECURE_ROM_SZ;
+  VirtualMemoryTable[Index].Attributes      = CacheAttributes;
+
+  // Juno OnChip peripherals
+  VirtualMemoryTable[++Index].PhysicalBase  = ARM_JUNO_PERIPHERALS_BASE;
+  VirtualMemoryTable[Index].VirtualBase     = ARM_JUNO_PERIPHERALS_BASE;
+  VirtualMemoryTable[Index].Length          = ARM_JUNO_PERIPHERALS_SZ;
+  VirtualMemoryTable[Index].Attributes      = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+
+  // Juno OnChip non-secure SRAM
+  VirtualMemoryTable[++Index].PhysicalBase  = ARM_JUNO_NON_SECURE_SRAM_BASE;
+  VirtualMemoryTable[Index].VirtualBase     = ARM_JUNO_NON_SECURE_SRAM_BASE;
+  VirtualMemoryTable[Index].Length          = ARM_JUNO_NON_SECURE_SRAM_SZ;
+  VirtualMemoryTable[Index].Attributes      = CacheAttributes;
+
+  // PCI Root Complex
+  VirtualMemoryTable[++Index].PhysicalBase  = PcdGet64 (PcdPcieControlBaseAddress);
+  VirtualMemoryTable[Index].VirtualBase     = PcdGet64 (PcdPcieControlBaseAddress);
+  VirtualMemoryTable[Index].Length          = SIZE_128KB;
+  VirtualMemoryTable[Index].Attributes      = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+
+  //
+  // PCI Configuration Space
+  //
+  VirtualMemoryTable[++Index].PhysicalBase  = PcdGet64 (PcdPciConfigurationSpaceBaseAddress);
+  VirtualMemoryTable[Index].VirtualBase     = PcdGet64 (PcdPciConfigurationSpaceBaseAddress);
+  VirtualMemoryTable[Index].Length          = PcdGet64 (PcdPciConfigurationSpaceSize);
+  VirtualMemoryTable[Index].Attributes      = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+
+  //
+  // PCI Memory Space
+  //
+  VirtualMemoryTable[++Index].PhysicalBase  = PcdGet32 (PcdPciMmio32Base);
+  VirtualMemoryTable[Index].VirtualBase     = PcdGet32 (PcdPciMmio32Base);
+  VirtualMemoryTable[Index].Length          = PcdGet32 (PcdPciMmio32Size);
+  VirtualMemoryTable[Index].Attributes      = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+
+  //
+  // 64-bit PCI Memory Space
+  //
+  VirtualMemoryTable[++Index].PhysicalBase  = PcdGet64 (PcdPciMmio64Base);
+  VirtualMemoryTable[Index].VirtualBase     = PcdGet64 (PcdPciMmio64Base);
+  VirtualMemoryTable[Index].Length          = PcdGet64 (PcdPciMmio64Size);
+  VirtualMemoryTable[Index].Attributes      = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+
+  // Juno SOC peripherals
+  VirtualMemoryTable[++Index].PhysicalBase  = ARM_JUNO_SOC_PERIPHERALS_BASE;
+  VirtualMemoryTable[Index].VirtualBase     = ARM_JUNO_SOC_PERIPHERALS_BASE;
+  VirtualMemoryTable[Index].Length          = ARM_JUNO_SOC_PERIPHERALS_SZ;
+  VirtualMemoryTable[Index].Attributes      = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+
+  // DDR - 2GB
+  VirtualMemoryTable[++Index].PhysicalBase  = PcdGet64 (PcdSystemMemoryBase);
+  VirtualMemoryTable[Index].VirtualBase     = PcdGet64 (PcdSystemMemoryBase);
+  VirtualMemoryTable[Index].Length          = PcdGet64 (PcdSystemMemorySize);
+  VirtualMemoryTable[Index].Attributes      = CacheAttributes;
+
+  // DDR - 6GB
+  VirtualMemoryTable[++Index].PhysicalBase  = ARM_JUNO_EXTRA_SYSTEM_MEMORY_BASE;
+  VirtualMemoryTable[Index].VirtualBase     = ARM_JUNO_EXTRA_SYSTEM_MEMORY_BASE;
+  VirtualMemoryTable[Index].Length          = ARM_JUNO_EXTRA_SYSTEM_MEMORY_SZ;
+  VirtualMemoryTable[Index].Attributes      = CacheAttributes;
+
+  // End of Table
+  VirtualMemoryTable[++Index].PhysicalBase  = 0;
+  VirtualMemoryTable[Index].VirtualBase     = 0;
+  VirtualMemoryTable[Index].Length          = 0;
+  VirtualMemoryTable[Index].Attributes      = (ARM_MEMORY_REGION_ATTRIBUTES)0;
+
+  ASSERT((Index + 1) <= MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS);
+
+  *VirtualMemoryMap = VirtualMemoryTable;
+}
diff --git a/Platform/ARM/JunoPkg/Library/JunoPciHostBridgeLib/JunoPciHostBridgeLib.inf b/Platform/ARM/JunoPkg/Library/JunoPciHostBridgeLib/JunoPciHostBridgeLib.inf
index 68e22396ccef..8f68f4b4f251 100644
--- a/Platform/ARM/JunoPkg/Library/JunoPciHostBridgeLib/JunoPciHostBridgeLib.inf
+++ b/Platform/ARM/JunoPkg/Library/JunoPciHostBridgeLib/JunoPciHostBridgeLib.inf
@@ -35,10 +35,10 @@ [Sources]
   XPressRich3.c
 
 [Packages]
-  ArmPlatformPkg/ArmJunoPkg/ArmJuno.dec
   ArmPkg/ArmPkg.dec
   MdeModulePkg/MdeModulePkg.dec
   MdePkg/MdePkg.dec
+  Platform/ARM/JunoPkg/ArmJuno.dec
 
 [LibraryClasses]
   BaseLib
diff --git a/Platform/ARM/JunoPkg/Library/NorFlashJunoLib/NorFlashJuno.c b/Platform/ARM/JunoPkg/Library/NorFlashJunoLib/NorFlashJuno.c
new file mode 100644
index 000000000000..b31b9635b7b7
--- /dev/null
+++ b/Platform/ARM/JunoPkg/Library/NorFlashJunoLib/NorFlashJuno.c
@@ -0,0 +1,68 @@
+/** @file
+
+ Copyright (c) 2011-2014, ARM Ltd. All rights reserved.<BR>
+
+ 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 <PiDxe.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/NorFlashPlatformLib.h>
+#include <ArmPlatform.h>
+
+NOR_FLASH_DESCRIPTION mNorFlashDevices[] = {
+  {
+    ARM_VE_SMB_NOR0_BASE,
+    ARM_VE_SMB_NOR0_BASE,
+    SIZE_256KB * 255,
+    SIZE_256KB,
+    {0xE7223039, 0x5836, 0x41E1, { 0xB5, 0x42, 0xD7, 0xEC, 0x73, 0x6C, 0x5E, 0x59} }
+  },
+  {
+    ARM_VE_SMB_NOR0_BASE,
+    ARM_VE_SMB_NOR0_BASE + SIZE_256KB * 255,
+    SIZE_64KB * 4,
+    SIZE_64KB,
+    {0x02118005, 0x9DA7, 0x443A, { 0x92, 0xD5, 0x78, 0x1F, 0x02, 0x2A, 0xED, 0xBB } }
+  },
+};
+
+EFI_STATUS
+NorFlashPlatformInitialization (
+  VOID
+  )
+{
+  // Everything seems ok so far, so now we need to disable the platform-specific
+  // flash write protection for Versatile Express
+  if ((MmioRead32 (ARM_VE_SYS_FLASH) & 0x1) == 0) {
+    // Writing to NOR FLASH is disabled, so enable it
+    MmioWrite32 (ARM_VE_SYS_FLASH, 1);
+    DEBUG((DEBUG_BLKIO, "NorFlashPlatformInitialization: informational - Had to enable HSYS_FLASH flag.\n" ));
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+NorFlashPlatformGetDevices (
+  OUT NOR_FLASH_DESCRIPTION   **NorFlashDevices,
+  OUT UINT32                  *Count
+  )
+{
+  if ((NorFlashDevices == NULL) || (Count == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *NorFlashDevices = mNorFlashDevices;
+  *Count = sizeof (mNorFlashDevices) / sizeof (NOR_FLASH_DESCRIPTION);
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/ARM/JunoPkg/Library/NorFlashJunoLib/NorFlashJunoLib.inf b/Platform/ARM/JunoPkg/Library/NorFlashJunoLib/NorFlashJunoLib.inf
new file mode 100644
index 000000000000..881a479d85e8
--- /dev/null
+++ b/Platform/ARM/JunoPkg/Library/NorFlashJunoLib/NorFlashJunoLib.inf
@@ -0,0 +1,33 @@
+#/** @file
+#
+#  Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
+#  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.
+#
+#**/
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = NorFlashJunoLib
+  FILE_GUID                      = 3eb6cbc4-ce95-11e2-b1bd-00241d0c1ba8
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = NorFlashPlatformLib
+
+[Sources.common]
+  NorFlashJuno.c
+
+[Packages]
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  MdePkg/MdePkg.dec
+  Platform/ARM/JunoPkg/ArmJuno.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  IoLib
diff --git a/Platform/ARM/JunoPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf b/Platform/ARM/JunoPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
index 457e1ff552d2..a8305925cd2d 100644
--- a/Platform/ARM/JunoPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
+++ b/Platform/ARM/JunoPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
@@ -35,9 +35,9 @@ [Sources]
 [Packages]
   ArmPkg/ArmPkg.dec
   ArmPlatformPkg/ArmPlatformPkg.dec
-  ArmPlatformPkg/ArmJunoPkg/ArmJuno.dec
   MdeModulePkg/MdeModulePkg.dec
   MdePkg/MdePkg.dec
+  Platform/ARM/JunoPkg/ArmJuno.dec
 
 [LibraryClasses]
   ArmLib
diff --git a/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.dsc b/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.dsc
index efa41165e4ad..5db6731ec9ec 100644
--- a/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.dsc
+++ b/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.dsc
@@ -55,6 +55,18 @@ [LibraryClasses.common]
   TimerLib|ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf
   ArmSmcLib|ArmPkg/Library/ArmSmcLib/ArmSmcLib.inf
 
+[LibraryClasses.common.DXE_RUNTIME_DRIVER]
+  ArmPlatformSysConfigLib|ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressSysConfigRuntimeLib/ArmVExpressSysConfigRuntimeLib.inf
+
+[LibraryClasses.ARM]
+  #
+  # PSCI support in EL3 may not be available if we are not running under a PSCI
+  # compliant secure firmware. Assume PSCI on AARCH64, and fall back to the
+  # syscfg MMIO register implementation on ARM.
+  # This will not work at actual runtime.
+  #
+  ResetSystemLib|ArmPlatformPkg/ArmVExpressPkg/Library/ResetSystemLib/ResetSystemLib.inf
+
 [BuildOptions]
 !ifdef ARM_BIGLITTLE_TC2
   *_*_ARM_ARCHCC_FLAGS  = -DARM_BIGLITTLE_TC2=1
diff --git a/Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.dsc b/Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.dsc
index fc628ad08c9e..e02a78a9766c 100644
--- a/Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.dsc
+++ b/Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.dsc
@@ -61,6 +61,9 @@ [LibraryClasses.common]
 
   DtPlatformDtbLoaderLib|Platform/ARM/VExpressPkg/Library/ArmVExpressDtPlatformDtbLoaderLib/ArmVExpressDtPlatformDtbLoaderLib.inf
 
+[LibraryClasses.common.DXE_RUNTIME_DRIVER]
+  ArmPlatformSysConfigLib|ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressSysConfigRuntimeLib/ArmVExpressSysConfigRuntimeLib.inf
+
 [LibraryClasses.common.SEC]
   ArmPlatformLib|ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressLibRTSM/ArmVExpressLibSec.inf
 
diff --git a/Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc b/Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc
index 3db269086d5b..203a781d9bd5 100644
--- a/Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc
+++ b/Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc
@@ -234,21 +234,11 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER]
   HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
   MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
   CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
-  ArmPlatformSysConfigLib|ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressSysConfigRuntimeLib/ArmVExpressSysConfigRuntimeLib.inf
   ReportStatusCodeLib|MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/RuntimeDxeReportStatusCodeLib.inf
 !if $(SECURE_BOOT_ENABLE) == TRUE
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
 !endif
 
-[LibraryClasses.ARM]
-  #
-  # PSCI support in EL3 may not be available if we are not running under a PSCI
-  # compliant secure firmware. Assume PSCI on AARCH64, and fall back to the
-  # syscfg MMIO register implementation on ARM.
-  # This will not work at actual runtime.
-  #
-  ResetSystemLib|ArmPlatformPkg/ArmVExpressPkg/Library/ResetSystemLib/ResetSystemLib.inf
-
 [LibraryClasses.ARM, LibraryClasses.AARCH64]
   #
   # It is not possible to prevent the ARM compiler for generic intrinsic functions.
