[edk2,edk2-platforms,v2,06/13] Platform/ARM/VExpress: import VExpressPkg from EDK2

Message ID 20171116175839.30012-7-ard.biesheuvel@linaro.org
State New
Headers show
Series
  • Move ArmPlatformPkg stuff into edk2-platforms
Related show

Commit Message

Ard Biesheuvel Nov. 16, 2017, 5:58 p.m.
Import the pieces that are closely tied to the ARM Versatile Express
development platforms into edk2-platforms, so they can be removed from
upstream EDK2.

Note that this includes the LCD drivers, and the ArmPlatformSysConfigLib
library class, which is not used anywhere else.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

---
Note that this omits the CTA9x4 code, which is not used anymore.

 Platform/ARM/VExpressPkg/AcpiTables/AcpiTables.inf                                                 |   3 +-
 Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.dsc                                                  |  27 +-
 Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.fdf                                                  |  10 +-
 Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.dsc                                               |  17 +-
 Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.fdf                                               |   2 +-
 Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc                                                       |   8 +-
 Platform/ARM/VExpressPkg/ArmVExpressPkg.dec                                                        |  53 ++
 Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmFvpDxe.c                                        |  90 ++
 Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmFvpDxe.inf                                      |  39 +
 Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmHwDxe.c                                         |  38 +
 Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmHwDxe.inf                                       |  37 +
 Platform/ARM/VExpressPkg/Drivers/ArmVExpressFastBootDxe/ArmVExpressFastBoot.c                      | 519 ++++++++++++
 Platform/ARM/VExpressPkg/Drivers/ArmVExpressFastBootDxe/ArmVExpressFastBootDxe.inf                 |  51 ++
 Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/HdLcd.c                                      | 133 +++
 Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/HdLcdGraphicsOutputDxe.inf                   |  63 ++
 Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputBlt.c                       | 882 ++++++++++++++++++++
 Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.c                       | 393 +++++++++
 Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.h                       | 128 +++
 Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/PL111Lcd.c                                   | 126 +++
 Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/PL111LcdGraphicsOutputDxe.inf                |  59 ++
 Platform/ARM/VExpressPkg/Include/Drivers/HdLcd.h                                                   |  89 ++
 Platform/ARM/VExpressPkg/Include/Drivers/PL111Lcd.h                                                | 149 ++++
 Platform/ARM/VExpressPkg/Include/Library/ArmPlatformSysConfigLib.h                                 |  63 ++
 Platform/ARM/VExpressPkg/Include/Library/LcdPlatformLib.h                                          | 221 +++++
 Platform/ARM/VExpressPkg/Include/Platform/CTA15-A7/ArmPlatform.h                                   | 154 ++++
 Platform/ARM/VExpressPkg/Include/Platform/RTSM/ArmPlatform.h                                       |  79 ++
 Platform/ARM/VExpressPkg/Include/VExpressMotherBoard.h                                             | 140 ++++
 Platform/ARM/VExpressPkg/Library/ArmVExpressLibCTA15-A7/ArmVExpressLib.inf                         |  54 ++
 Platform/ARM/VExpressPkg/Library/ArmVExpressLibCTA15-A7/CTA15-A7.c                                 | 195 +++++
 Platform/ARM/VExpressPkg/Library/ArmVExpressLibCTA15-A7/CTA15-A7Helper.S                           |  81 ++
 Platform/ARM/VExpressPkg/Library/ArmVExpressLibCTA15-A7/CTA15-A7Helper.asm                         |  96 +++
 Platform/ARM/VExpressPkg/Library/ArmVExpressLibCTA15-A7/CTA15-A7Mem.c                              | 182 ++++
 Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/AArch64/RTSMHelper.S                           |  61 ++
 Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/Arm/RTSMHelper.S                               |  97 +++
 Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/Arm/RTSMHelper.asm                             | 118 +++
 Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/ArmVExpressLib.inf                             |  63 ++
 Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/ArmVExpressLibSec.inf                          |  59 ++
 Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/RTSM.c                                         | 209 +++++
 Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/RTSMMem.c                                      | 161 ++++
 Platform/ARM/VExpressPkg/Library/ArmVExpressSysConfigLib/ArmVExpressSysConfig.c                    | 273 ++++++
 Platform/ARM/VExpressPkg/Library/ArmVExpressSysConfigLib/ArmVExpressSysConfigLib.inf               |  35 +
 Platform/ARM/VExpressPkg/Library/ArmVExpressSysConfigRuntimeLib/ArmVExpressSysConfigRuntimeLib.c   | 283 +++++++
 Platform/ARM/VExpressPkg/Library/ArmVExpressSysConfigRuntimeLib/ArmVExpressSysConfigRuntimeLib.inf |  37 +
 Platform/ARM/VExpressPkg/Library/HdLcdArmVExpressLib/HdLcdArmVExpress.c                            | 285 +++++++
 Platform/ARM/VExpressPkg/Library/HdLcdArmVExpressLib/HdLcdArmVExpressLib.inf                       |  45 +
 Platform/ARM/VExpressPkg/Library/NorFlashArmVExpressLib/NorFlashArmVExpress.c                      |  84 ++
 Platform/ARM/VExpressPkg/Library/NorFlashArmVExpressLib/NorFlashArmVExpressLib.inf                 |  33 +
 Platform/ARM/VExpressPkg/Library/PL111LcdArmVExpressLib/PL111LcdArmVExpress.c                      | 370 ++++++++
 Platform/ARM/VExpressPkg/Library/PL111LcdArmVExpressLib/PL111LcdArmVExpressLib.inf                 |  44 +
 Platform/ARM/VExpressPkg/Library/ResetSystemLib/ResetSystemLib.c                                   | 111 +++
 Platform/ARM/VExpressPkg/Library/ResetSystemLib/ResetSystemLib.inf                                 |  36 +
 51 files changed, 6550 insertions(+), 35 deletions(-)

-- 
2.11.0

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Patch

diff --git a/Platform/ARM/VExpressPkg/AcpiTables/AcpiTables.inf b/Platform/ARM/VExpressPkg/AcpiTables/AcpiTables.inf
index cc0f06f53323..35685274a041 100644
--- a/Platform/ARM/VExpressPkg/AcpiTables/AcpiTables.inf
+++ b/Platform/ARM/VExpressPkg/AcpiTables/AcpiTables.inf
@@ -31,11 +31,10 @@  [Sources]
 [Packages]
   ArmPkg/ArmPkg.dec
   ArmPlatformPkg/ArmPlatformPkg.dec
-  ArmPlatformPkg/ArmVExpressPkg/ArmVExpressPkg.dec
   EmbeddedPkg/EmbeddedPkg.dec
   MdePkg/MdePkg.dec
   MdeModulePkg/MdeModulePkg.dec
-
+  Platform/ARM/VExpressPkg/ArmVExpressPkg.dec
 
 [FixedPcd]
   gArmTokenSpaceGuid.PcdGicDistributorBase
diff --git a/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.dsc b/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.dsc
index 5db6731ec9ec..51da85fe8bc0 100644
--- a/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.dsc
+++ b/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.dsc
@@ -40,23 +40,22 @@  [Defines]
 [LibraryClasses.common]
   ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
   ArmMmuLib|ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf
-  ArmPlatformLib|ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressLibCTA15-A7/ArmVExpressLib.inf
+  ArmPlatformLib|Platform/ARM/VExpressPkg/Library/ArmVExpressLibCTA15-A7/ArmVExpressLib.inf
 
-  ArmPlatformSysConfigLib|ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressSysConfigLib/ArmVExpressSysConfigLib.inf
-  NorFlashPlatformLib|ArmPlatformPkg/ArmVExpressPkg/Library/NorFlashArmVExpressLib/NorFlashArmVExpressLib.inf
+  ArmPlatformSysConfigLib|Platform/ARM/VExpressPkg/Library/ArmVExpressSysConfigLib/ArmVExpressSysConfigLib.inf
 
-  #DebugAgentTimerLib|ArmPlatformPkg/ArmVExpressPkg/Library/DebugAgentTimerLib/DebugAgentTimerLib.inf
+  #DebugAgentTimerLib|Platform/ARM/VExpressPkg/Library/DebugAgentTimerLib/DebugAgentTimerLib.inf
 
   # ARM General Interrupt Driver in Secure and Non-secure
   ArmGicLib|ArmPkg/Drivers/ArmGic/ArmGicLib.inf
 
-  LcdPlatformLib|ArmPlatformPkg/ArmVExpressPkg/Library/HdLcdArmVExpressLib/HdLcdArmVExpressLib.inf
+  LcdPlatformLib|Platform/ARM/VExpressPkg/Library/HdLcdArmVExpressLib/HdLcdArmVExpressLib.inf
 
   TimerLib|ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf
   ArmSmcLib|ArmPkg/Library/ArmSmcLib/ArmSmcLib.inf
 
 [LibraryClasses.common.DXE_RUNTIME_DRIVER]
-  ArmPlatformSysConfigLib|ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressSysConfigRuntimeLib/ArmVExpressSysConfigRuntimeLib.inf
+  ArmPlatformSysConfigLib|Platform/ARM/VExpressPkg/Library/ArmVExpressSysConfigRuntimeLib/ArmVExpressSysConfigRuntimeLib.inf
 
 [LibraryClasses.ARM]
   #
@@ -65,7 +64,7 @@  [LibraryClasses.ARM]
   # syscfg MMIO register implementation on ARM.
   # This will not work at actual runtime.
   #
-  ResetSystemLib|ArmPlatformPkg/ArmVExpressPkg/Library/ResetSystemLib/ResetSystemLib.inf
+  ResetSystemLib|Platform/ARM/VExpressPkg/Library/ResetSystemLib/ResetSystemLib.inf
 
 [BuildOptions]
 !ifdef ARM_BIGLITTLE_TC2
@@ -73,11 +72,11 @@  [BuildOptions]
   *_*_ARM_PP_FLAGS  = -DARM_BIGLITTLE_TC2=1
 !endif
 
-  RVCT:*_*_ARM_PLATFORM_FLAGS == --cpu Cortex-A15 -I$(WORKSPACE)/ArmPlatformPkg/ArmVExpressPkg/Include -I$(WORKSPACE)/ArmPlatformPkg/ArmVExpressPkg/Include/Platform/CTA15-A7
+  RVCT:*_*_ARM_PLATFORM_FLAGS == --cpu Cortex-A15 -I$(WORKSPACE)/Platform/ARM/VExpressPkg/Include/Platform/CTA15-A7
 
-  GCC:*_*_ARM_PLATFORM_FLAGS == -mcpu=cortex-a15 -I$(WORKSPACE)/ArmPlatformPkg/ArmVExpressPkg/Include -I$(WORKSPACE)/ArmPlatformPkg/ArmVExpressPkg/Include/Platform/CTA15-A7
+  GCC:*_*_ARM_PLATFORM_FLAGS == -mcpu=cortex-a15 -I$(WORKSPACE)/Platform/ARM/VExpressPkg/Include/Platform/CTA15-A7
 
-  XCODE:*_*_ARM_PLATFORM_FLAGS = -I$(WORKSPACE)/ArmPlatformPkg/ArmVExpressPkg/Include -I$(WORKSPACE)/ArmPlatformPkg/ArmVExpressPkg/Include/Platform/CTA15-A7
+  XCODE:*_*_ARM_PLATFORM_FLAGS = -I$(WORKSPACE)/Platform/ARM/VExpressPkg/Include/Platform/CTA15-A7
 
 ################################################################################
 #
@@ -209,7 +208,7 @@  [Components.common]
   #
   ArmPlatformPkg/PrePi/PeiMPCore.inf {
     <LibraryClasses>
-      ArmPlatformLib|ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressLibCTA15-A7/ArmVExpressLib.inf
+      ArmPlatformLib|Platform/ARM/VExpressPkg/Library/ArmVExpressLibCTA15-A7/ArmVExpressLib.inf
   }
 
   #
@@ -248,15 +247,15 @@  [Components.common]
 
   ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
   ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
-  #ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/PL111LcdGraphicsOutputDxe.inf
-  ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/HdLcdGraphicsOutputDxe.inf
+  #Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/PL111LcdGraphicsOutputDxe.inf
+  Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/HdLcdGraphicsOutputDxe.inf
   ArmPkg/Drivers/TimerDxe/TimerDxe.inf
   ArmPlatformPkg/Drivers/SP805WatchdogDxe/SP805WatchdogDxe.inf
 
   #
   # Platform
   #
-  ArmPlatformPkg/ArmVExpressPkg/ArmVExpressDxe/ArmHwDxe.inf
+  Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmHwDxe.inf
 
   #
   # Filesystems
diff --git a/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.fdf b/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.fdf
index cb9a89ef0c7f..d33c3b79f84c 100644
--- a/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.fdf
+++ b/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.fdf
@@ -97,14 +97,14 @@  [FV.FvMain]
   INF ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
   INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf
   INF ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
-  #INF ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/PL111LcdGraphicsOutputDxe.inf
-  INF ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/HdLcdGraphicsOutputDxe.inf
+  #INF Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/PL111LcdGraphicsOutputDxe.inf
+  INF Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/HdLcdGraphicsOutputDxe.inf
   INF ArmPlatformPkg/Drivers/SP805WatchdogDxe/SP805WatchdogDxe.inf
 
   #
   # Platform
   #
-  INF ArmPlatformPkg/ArmVExpressPkg/ArmVExpressDxe/ArmHwDxe.inf
+  INF Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmHwDxe.inf
 
   #
   # Multimedia Card Interface
@@ -140,7 +140,7 @@  [FV.FvMain]
   #
   INF EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.inf
   INF EmbeddedPkg/Drivers/AndroidFastbootTransportUsbDxe/FastbootTransportUsbDxe.inf
-  INF ArmPlatformPkg/ArmVExpressPkg/ArmVExpressFastBootDxe/ArmVExpressFastBootDxe.inf
+  INF Platform/ARM/VExpressPkg/Drivers/ArmVExpressFastBootDxe/ArmVExpressFastBootDxe.inf
 
   # ACPI Support
   INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
@@ -187,7 +187,7 @@  [FV.FvMain]
 
   # Example to add a Device Tree to the Firmware Volume
   #FILE FREEFORM = PCD(gArmVExpressTokenSpaceGuid.PcdFdtVExpressHwA15x2A7x3) {
-  #  SECTION RAW = ArmPlatformPkg/ArmVExpressPkg/Fdts/vexpress-v2p-ca15_a7.dtb
+  #  SECTION RAW = Platform/ARM/VExpressPkg/Fdts/vexpress-v2p-ca15_a7.dtb
   #}
 
 [FV.FVMAIN_COMPACT]
diff --git a/Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.dsc b/Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.dsc
index e02a78a9766c..df6951900ed8 100644
--- a/Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.dsc
+++ b/Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.dsc
@@ -41,13 +41,12 @@  [Defines]
 
 [LibraryClasses.common]
   ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
-  ArmPlatformLib|ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressLibRTSM/ArmVExpressLib.inf
+  ArmPlatformLib|Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/ArmVExpressLib.inf
   ArmMmuLib|ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf
 
-  ArmPlatformSysConfigLib|ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressSysConfigLib/ArmVExpressSysConfigLib.inf
-  NorFlashPlatformLib|ArmPlatformPkg/ArmVExpressPkg/Library/NorFlashArmVExpressLib/NorFlashArmVExpressLib.inf
+  ArmPlatformSysConfigLib|Platform/ARM/VExpressPkg/Library/ArmVExpressSysConfigLib/ArmVExpressSysConfigLib.inf
 !ifdef EDK2_ENABLE_PL111
-  LcdPlatformLib|ArmPlatformPkg/ArmVExpressPkg/Library/PL111LcdArmVExpressLib/PL111LcdArmVExpressLib.inf
+  LcdPlatformLib|Platform/ARM/VExpressPkg/Library/PL111LcdArmVExpressLib/PL111LcdArmVExpressLib.inf
 !endif
 
   TimerLib|ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf
@@ -62,16 +61,16 @@  [LibraryClasses.common]
   DtPlatformDtbLoaderLib|Platform/ARM/VExpressPkg/Library/ArmVExpressDtPlatformDtbLoaderLib/ArmVExpressDtPlatformDtbLoaderLib.inf
 
 [LibraryClasses.common.DXE_RUNTIME_DRIVER]
-  ArmPlatformSysConfigLib|ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressSysConfigRuntimeLib/ArmVExpressSysConfigRuntimeLib.inf
+  ArmPlatformSysConfigLib|Platform/ARM/VExpressPkg/Library/ArmVExpressSysConfigRuntimeLib/ArmVExpressSysConfigRuntimeLib.inf
 
 [LibraryClasses.common.SEC]
-  ArmPlatformLib|ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressLibRTSM/ArmVExpressLibSec.inf
+  ArmPlatformLib|Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/ArmVExpressLibSec.inf
 
 [LibraryClasses.common.UEFI_DRIVER, LibraryClasses.common.UEFI_APPLICATION, LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses.common.DXE_DRIVER]
   PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
 
 [BuildOptions]
-  GCC:*_*_AARCH64_PLATFORM_FLAGS == -I$(WORKSPACE)/ArmPlatformPkg/ArmVExpressPkg/Include -I$(WORKSPACE)/ArmPlatformPkg/ArmVExpressPkg/Include/Platform/RTSM
+  GCC:*_*_AARCH64_PLATFORM_FLAGS == -I$(WORKSPACE)/Platform/ARM/VExpressPkg/Include/Platform/RTSM
 
 
 ################################################################################
@@ -196,7 +195,7 @@  [Components.common]
   # UEFI is placed in RAM by bootloader
   ArmPlatformPkg/PrePi/PeiUniCore.inf {
     <LibraryClasses>
-      ArmPlatformLib|ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressLibRTSM/ArmVExpressLib.inf
+      ArmPlatformLib|Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/ArmVExpressLib.inf
   }
 !else
   # UEFI lives in FLASH and copies itself to RAM
@@ -298,7 +297,7 @@  [Components.common]
   #
   # Platform Driver
   #
-  ArmPlatformPkg/ArmVExpressPkg/ArmVExpressDxe/ArmFvpDxe.inf
+  Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmFvpDxe.inf
   OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
 
   #
diff --git a/Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.fdf b/Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.fdf
index 1084eda3d367..0bac8ae91dab 100644
--- a/Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.fdf
+++ b/Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.fdf
@@ -145,7 +145,7 @@  [FV.FvMain]
   #
   # Platform Driver
   #
-  INF ArmPlatformPkg/ArmVExpressPkg/ArmVExpressDxe/ArmFvpDxe.inf
+  INF Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmFvpDxe.inf
   INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
 
 !ifdef EDK2_ENABLE_SMSC_91X
diff --git a/Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc b/Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc
index 203a781d9bd5..40e1c868fcb2 100644
--- a/Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc
+++ b/Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc
@@ -78,12 +78,12 @@  [LibraryClasses.common]
 
   # Versatile Express Specific Libraries
   PlatformPeiLib|ArmPlatformPkg/PlatformPei/PlatformPeiLib.inf
-  ArmPlatformSysConfigLib|ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressSysConfigLib/ArmVExpressSysConfigLib.inf
-  NorFlashPlatformLib|ArmPlatformPkg/ArmVExpressPkg/Library/NorFlashArmVExpressLib/NorFlashArmVExpressLib.inf
+  ArmPlatformSysConfigLib|Platform/ARM/VExpressPkg/Library/ArmVExpressSysConfigLib/ArmVExpressSysConfigLib.inf
+  NorFlashPlatformLib|Platform/ARM/VExpressPkg/Library/NorFlashArmVExpressLib/NorFlashArmVExpressLib.inf
   ResetSystemLib|ArmPkg/Library/ArmSmcPsciResetSystemLib/ArmSmcPsciResetSystemLib.inf
 !ifdef EDK2_ENABLE_PL111
   # ARM PL111 Lcd Driver
-  LcdPlatformLib|ArmPlatformPkg/ArmVExpressPkg/Library/PL111LcdArmVExpressLib/PL111LcdArmVExpressLib.inf
+  LcdPlatformLib|Platform/ARM/VExpressPkg/Library/PL111LcdArmVExpressLib/PL111LcdArmVExpressLib.inf
 !endif
   # ARM PL031 RTC Driver
   RealTimeClockLib|ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.inf
@@ -472,7 +472,7 @@  [Components.common]
       BdsLib|ArmPkg/Library/BdsLib/BdsLib.inf
   }
   EmbeddedPkg/Drivers/AndroidFastbootTransportUsbDxe/FastbootTransportUsbDxe.inf
-  ArmPlatformPkg/ArmVExpressPkg/ArmVExpressFastBootDxe/ArmVExpressFastBootDxe.inf
+  Platform/ARM/VExpressPkg/Drivers/ArmVExpressFastBootDxe/ArmVExpressFastBootDxe.inf
 
   # FV Filesystem
   MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemDxe.inf
diff --git a/Platform/ARM/VExpressPkg/ArmVExpressPkg.dec b/Platform/ARM/VExpressPkg/ArmVExpressPkg.dec
new file mode 100644
index 000000000000..3814513c2241
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/ArmVExpressPkg.dec
@@ -0,0 +1,53 @@ 
+#/** @file
+# Arm Versatile Express package.
+#
+#  Copyright (c) 2012-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              = 0x00010005
+  PACKAGE_NAME                   = ArmVExpressPkg
+  PACKAGE_GUID                   = 9c0aaed4-74c5-4043-b417-a3223814ce76
+  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]
+  gArmVExpressTokenSpaceGuid    =  { 0x9c0aaed4, 0x74c5, 0x4043, { 0xb4, 0x17, 0xa3, 0x22, 0x38, 0x14, 0xce, 0x76 } }
+
+[PcdsFeatureFlag.common]
+
+[PcdsFixedAtBuild.common]
+  #
+  # MaxMode must be one number higher than the actual max mode,
+  # i.e. for actual maximum mode 2, set the value to 3.
+  #
+  # For a list of mode numbers look in LcdArmVExpress.c
+  #
+  gArmVExpressTokenSpaceGuid.PcdPL111LcdMaxMode|3|UINT32|0x00000001
+  gArmVExpressTokenSpaceGuid.PcdPL111LcdVideoModeOscId|1|UINT32|0x00000002
+  gArmVExpressTokenSpaceGuid.PcdHdLcdVideoModeOscId|0|UINT32|0x00000003
+
+  #
+  # Device path of block device on which Fastboot will flash partitions
+  #
+  gArmVExpressTokenSpaceGuid.PcdAndroidFastbootNvmDevicePath|""|VOID*|0x00000004
diff --git a/Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmFvpDxe.c b/Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmFvpDxe.c
new file mode 100644
index 000000000000..7827c50d8bbf
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmFvpDxe.c
@@ -0,0 +1,90 @@ 
+/** @file
+
+  Copyright (c) 2013-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 <PiDxe.h>
+
+#include <Library/ArmShellCmdLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/VirtioMmioDeviceLib.h>
+
+#include <VExpressMotherBoard.h>
+
+#define ARM_FVP_BASE_VIRTIO_BLOCK_BASE    0x1c130000
+
+#pragma pack(1)
+typedef struct {
+  VENDOR_DEVICE_PATH                  Vendor;
+  EFI_DEVICE_PATH_PROTOCOL            End;
+} VIRTIO_BLK_DEVICE_PATH;
+#pragma pack()
+
+VIRTIO_BLK_DEVICE_PATH mVirtioBlockDevicePath =
+{
+  {
+    {
+      HARDWARE_DEVICE_PATH,
+      HW_VENDOR_DP,
+      {
+        (UINT8)( sizeof(VENDOR_DEVICE_PATH) ),
+        (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8)
+      }
+    },
+    EFI_CALLER_ID_GUID,
+  },
+  {
+    END_DEVICE_PATH_TYPE,
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,
+    {
+      sizeof (EFI_DEVICE_PATH_PROTOCOL),
+      0
+    }
+  }
+};
+
+/**
+ * Generic UEFI Entrypoint for 'ArmFvpDxe' driver
+ * See UEFI specification for the details of the parameters
+ */
+EFI_STATUS
+EFIAPI
+ArmFvpInitialise (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS                   Status;
+
+  Status = gBS->InstallProtocolInterface (&ImageHandle,
+                 &gEfiDevicePathProtocolGuid, EFI_NATIVE_INTERFACE,
+                 &mVirtioBlockDevicePath);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  // Declare the Virtio BlockIo device
+  Status = VirtioMmioInstallDevice (ARM_FVP_BASE_VIRTIO_BLOCK_BASE, ImageHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "ArmFvpDxe: Failed to install Virtio block device\n"));
+  }
+
+  // Install dynamic Shell command to run baremetal binaries.
+  Status = ShellDynCmdRunAxfInstall (ImageHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "ArmFvpDxe: Failed to install ShellDynCmdRunAxf\n"));
+  }
+
+  return Status;
+}
diff --git a/Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmFvpDxe.inf b/Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmFvpDxe.inf
new file mode 100644
index 000000000000..1d208261201b
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmFvpDxe.inf
@@ -0,0 +1,39 @@ 
+#/** @file
+#
+#  Copyright (c) 2013-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.
+#
+#**/
+
+[Defines]
+  INF_VERSION                    = 0x00010006
+  BASE_NAME                      = ArmFvpDxe
+  FILE_GUID                      = 405b2307-6839-4d52-aeb9-bece64252800
+  MODULE_TYPE                    = UEFI_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = ArmFvpInitialise
+
+[Sources.common]
+  ArmFvpDxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  OvmfPkg/OvmfPkg.dec
+  Platform/ARM/VExpressPkg/ArmVExpressPkg.dec
+
+[LibraryClasses]
+  ArmShellCmdRunAxfLib
+  BaseMemoryLib
+  UefiDriverEntryPoint
+  UefiBootServicesTableLib
+  VirtioMmioDeviceLib
+
diff --git a/Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmHwDxe.c b/Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmHwDxe.c
new file mode 100644
index 000000000000..19efa3c23dea
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmHwDxe.c
@@ -0,0 +1,38 @@ 
+/** @file
+
+  Copyright (c) 2013-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 <Library/ArmShellCmdLib.h>
+#include <Library/DebugLib.h>
+
+/**
+ * Generic UEFI Entrypoint for 'ArmHwDxe' driver
+ * See UEFI specification for the details of the parameters
+ */
+EFI_STATUS
+EFIAPI
+ArmHwInitialise (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  // Install dynamic Shell command to run baremetal binaries.
+  Status = ShellDynCmdRunAxfInstall (ImageHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "ArmHwDxe: Failed to install ShellDynCmdRunAxf\n"));
+  }
+
+  return Status;
+}
diff --git a/Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmHwDxe.inf b/Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmHwDxe.inf
new file mode 100644
index 000000000000..1ecdbb0b231e
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmHwDxe.inf
@@ -0,0 +1,37 @@ 
+#/** @file
+#
+#  Copyright (c) 2013-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.
+#
+#**/
+
+[Defines]
+  INF_VERSION                    = 0x00010006
+  BASE_NAME                      = ArmHwDxe
+  FILE_GUID                      = fe61bb5f-1b67-4c24-b346-73db42e873e5
+  MODULE_TYPE                    = UEFI_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = ArmHwInitialise
+
+[Sources.common]
+  ArmHwDxe.c
+
+[Packages]
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  ArmShellCmdRunAxfLib
+  DxeServicesTableLib
+  MemoryAllocationLib
+  UefiDriverEntryPoint
+
+[Protocols]
+  gEfiDevicePathProtocolGuid
diff --git a/Platform/ARM/VExpressPkg/Drivers/ArmVExpressFastBootDxe/ArmVExpressFastBoot.c b/Platform/ARM/VExpressPkg/Drivers/ArmVExpressFastBootDxe/ArmVExpressFastBoot.c
new file mode 100644
index 000000000000..a01bf3c671ad
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Drivers/ArmVExpressFastBootDxe/ArmVExpressFastBoot.c
@@ -0,0 +1,519 @@ 
+/** @file
+
+  Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
+  Copyright (c) 2016, Linaro 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.
+
+**/
+
+/*
+  Implementation of the Android Fastboot Platform protocol, to be used by the
+  Fastboot UEFI application, for ARM Versatile Express platforms.
+*/
+
+#include <Protocol/AndroidFastbootPlatform.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/DiskIo.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#define FLASH_DEVICE_PATH_SIZE(DevPath) ( GetDevicePathSize (DevPath) - \
+                                            sizeof (EFI_DEVICE_PATH_PROTOCOL))
+
+#define PARTITION_NAME_MAX_LENGTH 72/2
+
+#define IS_ALPHA(Char) (((Char) <= L'z' && (Char) >= L'a') || \
+                        ((Char) <= L'Z' && (Char) >= L'Z'))
+
+typedef struct _FASTBOOT_PARTITION_LIST {
+  LIST_ENTRY  Link;
+  CHAR16      PartitionName[PARTITION_NAME_MAX_LENGTH];
+  EFI_HANDLE  PartitionHandle;
+} FASTBOOT_PARTITION_LIST;
+
+STATIC LIST_ENTRY mPartitionListHead;
+
+/*
+  Helper to free the partition list
+*/
+STATIC
+VOID
+FreePartitionList (
+  VOID
+  )
+{
+  FASTBOOT_PARTITION_LIST *Entry;
+  FASTBOOT_PARTITION_LIST *NextEntry;
+
+  Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&mPartitionListHead);
+  while (!IsNull (&mPartitionListHead, &Entry->Link)) {
+    NextEntry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &Entry->Link);
+
+    RemoveEntryList (&Entry->Link);
+    FreePool (Entry);
+
+    Entry = NextEntry;
+  }
+}
+/*
+  Read the PartitionName fields from the GPT partition entries, putting them
+  into an allocated array that should later be freed.
+*/
+STATIC
+EFI_STATUS
+ReadPartitionEntries (
+  IN  EFI_BLOCK_IO_PROTOCOL *BlockIo,
+  OUT EFI_PARTITION_ENTRY  **PartitionEntries
+  )
+{
+  UINTN                       EntrySize;
+  UINTN                       NumEntries;
+  UINTN                       BufferSize;
+  UINT32                      MediaId;
+  EFI_PARTITION_TABLE_HEADER *GptHeader;
+  EFI_STATUS                  Status;
+
+  MediaId = BlockIo->Media->MediaId;
+
+  //
+  // Read size of Partition entry and number of entries from GPT header
+  //
+
+  GptHeader = AllocatePool (BlockIo->Media->BlockSize);
+  if (GptHeader == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = BlockIo->ReadBlocks (BlockIo, MediaId, 1, BlockIo->Media->BlockSize, (VOID *) GptHeader);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  // Check there is a GPT on the media
+  if (GptHeader->Header.Signature != EFI_PTAB_HEADER_ID ||
+      GptHeader->MyLBA != 1) {
+    DEBUG ((EFI_D_ERROR,
+      "Fastboot platform: No GPT on flash. "
+      "Fastboot on Versatile Express does not support MBR.\n"
+      ));
+    return EFI_DEVICE_ERROR;
+  }
+
+  EntrySize = GptHeader->SizeOfPartitionEntry;
+  NumEntries = GptHeader->NumberOfPartitionEntries;
+
+  FreePool (GptHeader);
+
+  ASSERT (EntrySize != 0);
+  ASSERT (NumEntries != 0);
+
+  BufferSize = ALIGN_VALUE (EntrySize * NumEntries, BlockIo->Media->BlockSize);
+  *PartitionEntries = AllocatePool (BufferSize);
+  if (PartitionEntries == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = BlockIo->ReadBlocks (BlockIo, MediaId, 2, BufferSize, (VOID *) *PartitionEntries);
+  if (EFI_ERROR (Status)) {
+    FreePool (PartitionEntries);
+    return Status;
+  }
+
+  return Status;
+}
+
+
+/*
+  Do any initialisation that needs to be done in order to be able to respond to
+  commands.
+
+  @retval EFI_SUCCESS   Initialised successfully.
+  @retval !EFI_SUCCESS  Error in initialisation.
+*/
+STATIC
+EFI_STATUS
+ArmFastbootPlatformInit (
+  VOID
+  )
+{
+  EFI_STATUS                          Status;
+  EFI_DEVICE_PATH_PROTOCOL           *FlashDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL           *FlashDevicePathDup;
+  EFI_DEVICE_PATH_PROTOCOL           *DevicePath;
+  EFI_DEVICE_PATH_PROTOCOL           *NextNode;
+  HARDDRIVE_DEVICE_PATH              *PartitionNode;
+  UINTN                               NumHandles;
+  EFI_HANDLE                         *AllHandles;
+  UINTN                               LoopIndex;
+  EFI_HANDLE                          FlashHandle;
+  EFI_BLOCK_IO_PROTOCOL              *FlashBlockIo;
+  EFI_PARTITION_ENTRY                *PartitionEntries;
+  FASTBOOT_PARTITION_LIST            *Entry;
+
+  InitializeListHead (&mPartitionListHead);
+
+  //
+  // Get EFI_HANDLES for all the partitions on the block devices pointed to by
+  // PcdFastbootFlashDevicePath, also saving their GPT partition labels.
+  // We will use these labels as the key in ArmFastbootPlatformFlashPartition.
+  // There's no way to find all of a device's children, so we get every handle
+  // in the system supporting EFI_BLOCK_IO_PROTOCOL and then filter out ones
+  // that don't represent partitions on the flash device.
+  //
+
+  FlashDevicePath = ConvertTextToDevicePath ((CHAR16*)FixedPcdGetPtr (PcdAndroidFastbootNvmDevicePath));
+
+  //
+  // Open the Disk IO protocol on the flash device - this will be used to read
+  // partition names out of the GPT entries
+  //
+  // Create another device path pointer because LocateDevicePath will modify it.
+  FlashDevicePathDup = FlashDevicePath;
+  Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &FlashDevicePathDup, &FlashHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "Warning: Couldn't locate Android NVM device (status: %r)\n", Status));
+    // Failing to locate partitions should not prevent to do other Android FastBoot actions
+    return EFI_SUCCESS;
+  }
+
+  Status = gBS->OpenProtocol (
+                  FlashHandle,
+                  &gEfiBlockIoProtocolGuid,
+                  (VOID **) &FlashBlockIo,
+                  gImageHandle,
+                  NULL,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "Fastboot platform: Couldn't open Android NVM device (status: %r)\n", Status));
+    return EFI_DEVICE_ERROR;
+  }
+
+  // Read the GPT partition entry array into memory so we can get the partition names
+  Status = ReadPartitionEntries (FlashBlockIo, &PartitionEntries);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "Warning: Failed to read partitions from Android NVM device (status: %r)\n", Status));
+    // Failing to locate partitions should not prevent to do other Android FastBoot actions
+    return EFI_SUCCESS;
+  }
+
+  // Get every Block IO protocol instance installed in the system
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiBlockIoProtocolGuid,
+                  NULL,
+                  &NumHandles,
+                  &AllHandles
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  // Filter out handles that aren't children of the flash device
+  for (LoopIndex = 0; LoopIndex < NumHandles; LoopIndex++) {
+    // Get the device path for the handle
+    Status = gBS->OpenProtocol (
+                    AllHandles[LoopIndex],
+                    &gEfiDevicePathProtocolGuid,
+                    (VOID **) &DevicePath,
+                    gImageHandle,
+                    NULL,
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                    );
+    ASSERT_EFI_ERROR (Status);
+
+    // Check if it is a sub-device of the flash device
+    if (!CompareMem (DevicePath, FlashDevicePath, FLASH_DEVICE_PATH_SIZE (FlashDevicePath))) {
+      // Device path starts with path of flash device. Check it isn't the flash
+      // device itself.
+      NextNode = NextDevicePathNode (DevicePath);
+      if (IsDevicePathEndType (NextNode)) {
+        continue;
+      }
+
+      // Assert that this device path node represents a partition.
+      ASSERT (NextNode->Type == MEDIA_DEVICE_PATH &&
+              NextNode->SubType == MEDIA_HARDDRIVE_DP);
+
+      PartitionNode = (HARDDRIVE_DEVICE_PATH *) NextNode;
+
+      // Assert that the partition type is GPT. ReadPartitionEntries checks for
+      // presence of a GPT, so we should never find MBR partitions.
+      // ("MBRType" is a misnomer - this field is actually called "Partition
+      //  Format")
+      ASSERT (PartitionNode->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER);
+
+      // The firmware may install a handle for "partition 0", representing the
+      // whole device. Ignore it.
+      if (PartitionNode->PartitionNumber == 0) {
+        continue;
+      }
+
+      //
+      // Add the partition handle to the list
+      //
+
+      // Create entry
+      Entry = AllocatePool (sizeof (FASTBOOT_PARTITION_LIST));
+      if (Entry == NULL) {
+        Status = EFI_OUT_OF_RESOURCES;
+        FreePartitionList ();
+        goto Exit;
+      }
+
+      // Copy handle and partition name
+      Entry->PartitionHandle = AllHandles[LoopIndex];
+      CopyMem (
+        Entry->PartitionName,
+        PartitionEntries[PartitionNode->PartitionNumber - 1].PartitionName, // Partition numbers start from 1.
+        PARTITION_NAME_MAX_LENGTH
+        );
+      InsertTailList (&mPartitionListHead, &Entry->Link);
+
+      // Print a debug message if the partition label is empty or looks like
+      // garbage.
+      if (!IS_ALPHA (Entry->PartitionName[0])) {
+        DEBUG ((EFI_D_ERROR,
+          "Warning: Partition %d doesn't seem to have a GPT partition label. "
+          "You won't be able to flash it with Fastboot.\n",
+          PartitionNode->PartitionNumber
+          ));
+      }
+    }
+  }
+
+Exit:
+  FreePool (PartitionEntries);
+  FreePool (FlashDevicePath);
+  FreePool (AllHandles);
+  return Status;
+
+}
+
+/*
+  To be called when Fastboot is finished and we aren't rebooting or booting an
+  image. Undo initialisation, free resrouces.
+*/
+STATIC
+VOID
+ArmFastbootPlatformUnInit (
+  VOID
+  )
+{
+  FreePartitionList ();
+}
+
+/*
+  Flash the partition named (according to a platform-specific scheme)
+  PartitionName, with the image pointed to by Buffer, whose size is BufferSize.
+
+  @param[in] PartitionName  Null-terminated name of partition to write.
+  @param[in] BufferSize     Size of Buffer in byets.
+  @param[in] Buffer         Data to write to partition.
+
+  @retval EFI_NOT_FOUND     No such partition.
+  @retval EFI_DEVICE_ERROR  Flashing failed.
+*/
+STATIC
+EFI_STATUS
+ArmFastbootPlatformFlashPartition (
+  IN CHAR8  *PartitionName,
+  IN UINTN   Size,
+  IN VOID   *Image
+  )
+{
+  EFI_STATUS               Status;
+  EFI_BLOCK_IO_PROTOCOL   *BlockIo;
+  EFI_DISK_IO_PROTOCOL    *DiskIo;
+  UINT32                   MediaId;
+  UINTN                    PartitionSize;
+  FASTBOOT_PARTITION_LIST *Entry;
+  CHAR16                   PartitionNameUnicode[60];
+  BOOLEAN                  PartitionFound;
+
+  AsciiStrToUnicodeStrS (PartitionName, PartitionNameUnicode,
+    ARRAY_SIZE (PartitionNameUnicode));
+
+  PartitionFound = FALSE;
+  Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&(mPartitionListHead));
+  while (!IsNull (&mPartitionListHead, &Entry->Link)) {
+    // Search the partition list for the partition named by PartitionName
+    if (StrCmp (Entry->PartitionName, PartitionNameUnicode) == 0) {
+      PartitionFound = TRUE;
+      break;
+    }
+
+   Entry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &(Entry)->Link);
+  }
+  if (!PartitionFound) {
+    return EFI_NOT_FOUND;
+  }
+
+  Status = gBS->OpenProtocol (
+                  Entry->PartitionHandle,
+                  &gEfiBlockIoProtocolGuid,
+                  (VOID **) &BlockIo,
+                  gImageHandle,
+                  NULL,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "Fastboot platform: couldn't open Block IO for flash: %r\n", Status));
+    return EFI_NOT_FOUND;
+  }
+
+  // Check image will fit on device
+  PartitionSize = (BlockIo->Media->LastBlock + 1) * BlockIo->Media->BlockSize;
+  if (PartitionSize < Size) {
+    DEBUG ((EFI_D_ERROR, "Partition not big enough.\n"));
+    DEBUG ((EFI_D_ERROR, "Partition Size:\t%d\nImage Size:\t%d\n", PartitionSize, Size));
+
+    return EFI_VOLUME_FULL;
+  }
+
+  MediaId = BlockIo->Media->MediaId;
+
+  Status = gBS->OpenProtocol (
+                  Entry->PartitionHandle,
+                  &gEfiDiskIoProtocolGuid,
+                  (VOID **) &DiskIo,
+                  gImageHandle,
+                  NULL,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = DiskIo->WriteDisk (DiskIo, MediaId, 0, Size, Image);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  BlockIo->FlushBlocks(BlockIo);
+
+  return Status;
+}
+
+/*
+  Erase the partition named PartitionName.
+
+  @param[in] PartitionName  Null-terminated name of partition to erase.
+
+  @retval EFI_NOT_FOUND     No such partition.
+  @retval EFI_DEVICE_ERROR  Erasing failed.
+*/
+STATIC
+EFI_STATUS
+ArmFastbootPlatformErasePartition (
+  IN CHAR8 *Partition
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/*
+  If the variable referred to by Name exists, copy it (as a null-terminated
+  string) into Value. If it doesn't exist, put the Empty string in Value.
+
+  Variable names and values may not be larger than 60 bytes, excluding the
+  terminal null character. This is a limitation of the Fastboot protocol.
+
+  The Fastboot application will handle platform-nonspecific variables
+  (Currently "version" is the only one of these.)
+
+  @param[in]  Name   Null-terminated name of Fastboot variable to retrieve.
+  @param[out] Value  Caller-allocated buffer for null-terminated value of
+                     variable.
+
+  @retval EFI_SUCCESS       The variable was retrieved, or it doesn't exist.
+  @retval EFI_DEVICE_ERROR  There was an error looking up the variable. This
+                            does _not_ include the variable not existing.
+*/
+STATIC
+EFI_STATUS
+ArmFastbootPlatformGetVar (
+  IN  CHAR8   *Name,
+  OUT CHAR8   *Value
+  )
+{
+  if (AsciiStrCmp (Name, "product")) {
+    AsciiStrCpyS (Value, 61, FixedPcdGetPtr (PcdFirmwareVendor));
+  } else {
+    *Value = '\0';
+  }
+  return EFI_SUCCESS;
+}
+
+/*
+  React to an OEM-specific command.
+
+  Future versions of this function might want to allow the platform to do some
+  extra communication with the host. A way to do this would be to add a function
+  to the FASTBOOT_TRANSPORT_PROTOCOL that allows the implementation of
+  DoOemCommand to replace the ReceiveEvent with its own, and to restore the old
+  one when it's finished.
+
+  However at the moment although the specification allows it, the AOSP fastboot
+  host application doesn't handle receiving any data from the client, and it
+  doesn't support a data phase for OEM commands.
+
+  @param[in] Command    Null-terminated command string.
+
+  @retval EFI_SUCCESS       The command executed successfully.
+  @retval EFI_NOT_FOUND     The command wasn't recognised.
+  @retval EFI_DEVICE_ERROR  There was an error executing the command.
+*/
+STATIC
+EFI_STATUS
+ArmFastbootPlatformOemCommand (
+  IN  CHAR8   *Command
+  )
+{
+  CHAR16 CommandUnicode[65];
+
+  AsciiStrToUnicodeStrS (Command, CommandUnicode, ARRAY_SIZE (CommandUnicode));
+
+  if (AsciiStrCmp (Command, "Demonstrate") == 0) {
+    DEBUG ((EFI_D_ERROR, "ARM OEM Fastboot command 'Demonstrate' received.\n"));
+    return EFI_SUCCESS;
+  } else {
+    DEBUG ((EFI_D_ERROR,
+      "VExpress: Unrecognised Fastboot OEM command: %s\n",
+      CommandUnicode
+      ));
+    return EFI_NOT_FOUND;
+  }
+}
+
+STATIC FASTBOOT_PLATFORM_PROTOCOL mPlatformProtocol = {
+  ArmFastbootPlatformInit,
+  ArmFastbootPlatformUnInit,
+  ArmFastbootPlatformFlashPartition,
+  ArmFastbootPlatformErasePartition,
+  ArmFastbootPlatformGetVar,
+  ArmFastbootPlatformOemCommand
+};
+
+EFI_STATUS
+EFIAPI
+ArmAndroidFastbootPlatformEntryPoint (
+  IN EFI_HANDLE                            ImageHandle,
+  IN EFI_SYSTEM_TABLE                      *SystemTable
+  )
+{
+  return gBS->InstallProtocolInterface (
+                &ImageHandle,
+                &gAndroidFastbootPlatformProtocolGuid,
+                EFI_NATIVE_INTERFACE,
+                &mPlatformProtocol
+                );
+}
diff --git a/Platform/ARM/VExpressPkg/Drivers/ArmVExpressFastBootDxe/ArmVExpressFastBootDxe.inf b/Platform/ARM/VExpressPkg/Drivers/ArmVExpressFastBootDxe/ArmVExpressFastBootDxe.inf
new file mode 100644
index 000000000000..07c5e1e230e9
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Drivers/ArmVExpressFastBootDxe/ArmVExpressFastBootDxe.inf
@@ -0,0 +1,51 @@ 
+#/** @file
+#
+#  Copyright (c) 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                      = ArmVExpressFastBootDxe
+  FILE_GUID                      = 4004e454-89a0-11e3-89aa-97ef9d942abc
+  MODULE_TYPE                    = UEFI_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = ArmAndroidFastbootPlatformEntryPoint
+
+[Sources.common]
+  ArmVExpressFastBoot.c
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  DevicePathLib
+  MemoryAllocationLib
+  PcdLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+
+[Protocols]
+  gAndroidFastbootPlatformProtocolGuid
+  gEfiBlockIoProtocolGuid
+  gEfiDiskIoProtocolGuid
+
+[Packages]
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  ArmPkg/ArmPkg.dec
+  Platform/ARM/VExpressPkg/ArmVExpressPkg.dec
+
+[Pcd]
+  gArmVExpressTokenSpaceGuid.PcdAndroidFastbootNvmDevicePath
+  gArmPlatformTokenSpaceGuid.PcdFirmwareVendor
diff --git a/Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/HdLcd.c b/Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/HdLcd.c
new file mode 100644
index 000000000000..2bfe2c0fe2dc
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/HdLcd.c
@@ -0,0 +1,133 @@ 
+/** @file  Lcd.c
+
+  Copyright (c) 2011-2012, 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 <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/LcdPlatformLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+
+#include <Drivers/HdLcd.h>
+
+#include "LcdGraphicsOutputDxe.h"
+
+/**********************************************************************
+ *
+ *  This file contains all the bits of the Lcd that are
+ *  platform independent.
+ *
+ **********************************************************************/
+
+EFI_STATUS
+LcdInitialize (
+  IN EFI_PHYSICAL_ADDRESS   VramBaseAddress
+  )
+{
+  // Disable the controller
+  MmioWrite32(HDLCD_REG_COMMAND, HDLCD_DISABLE);
+
+  // Disable all interrupts
+  MmioWrite32(HDLCD_REG_INT_MASK, 0);
+
+  // Define start of the VRAM. This never changes for any graphics mode
+  MmioWrite32(HDLCD_REG_FB_BASE, (UINT32) VramBaseAddress);
+
+  // Setup various registers that never change
+  MmioWrite32(HDLCD_REG_BUS_OPTIONS,  (4 << 8) | HDLCD_BURST_8);
+  MmioWrite32(HDLCD_REG_POLARITIES,   HDLCD_PXCLK_LOW | HDLCD_DATA_HIGH | HDLCD_DATEN_HIGH | HDLCD_HSYNC_LOW | HDLCD_VSYNC_HIGH);
+  MmioWrite32(HDLCD_REG_PIXEL_FORMAT, HDLCD_LITTLE_ENDIAN | HDLCD_4BYTES_PER_PIXEL);
+  MmioWrite32(HDLCD_REG_RED_SELECT,   (0 << 16 | 8 << 8 |  0));
+  MmioWrite32(HDLCD_REG_GREEN_SELECT, (0 << 16 | 8 << 8 |  8));
+  MmioWrite32(HDLCD_REG_BLUE_SELECT,  (0 << 16 | 8 << 8 | 16));
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+LcdSetMode (
+  IN UINT32  ModeNumber
+  )
+{
+  EFI_STATUS        Status;
+  UINT32            HRes;
+  UINT32            HSync;
+  UINT32            HBackPorch;
+  UINT32            HFrontPorch;
+  UINT32            VRes;
+  UINT32            VSync;
+  UINT32            VBackPorch;
+  UINT32            VFrontPorch;
+  UINT32            BytesPerPixel;
+  LCD_BPP           LcdBpp;
+
+
+  // Set the video mode timings and other relevant information
+  Status = LcdPlatformGetTimings (ModeNumber,
+                                  &HRes,&HSync,&HBackPorch,&HFrontPorch,
+                                  &VRes,&VSync,&VBackPorch,&VFrontPorch);
+  ASSERT_EFI_ERROR (Status);
+  if (EFI_ERROR( Status )) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  Status = LcdPlatformGetBpp (ModeNumber,&LcdBpp);
+  ASSERT_EFI_ERROR (Status);
+  if (EFI_ERROR( Status )) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  BytesPerPixel = GetBytesPerPixel(LcdBpp);
+
+  // Disable the controller
+  MmioWrite32(HDLCD_REG_COMMAND, HDLCD_DISABLE);
+
+  // Update the frame buffer information with the new settings
+  MmioWrite32(HDLCD_REG_FB_LINE_LENGTH, HRes * BytesPerPixel);
+  MmioWrite32(HDLCD_REG_FB_LINE_PITCH,  HRes * BytesPerPixel);
+  MmioWrite32(HDLCD_REG_FB_LINE_COUNT,  VRes - 1);
+
+  // Set the vertical timing information
+  MmioWrite32(HDLCD_REG_V_SYNC,         VSync);
+  MmioWrite32(HDLCD_REG_V_BACK_PORCH,   VBackPorch);
+  MmioWrite32(HDLCD_REG_V_DATA,         VRes - 1);
+  MmioWrite32(HDLCD_REG_V_FRONT_PORCH,  VFrontPorch);
+
+  // Set the horizontal timing information
+  MmioWrite32(HDLCD_REG_H_SYNC,         HSync);
+  MmioWrite32(HDLCD_REG_H_BACK_PORCH,   HBackPorch);
+  MmioWrite32(HDLCD_REG_H_DATA,         HRes - 1);
+  MmioWrite32(HDLCD_REG_H_FRONT_PORCH,  HFrontPorch);
+
+  // Enable the controller
+  MmioWrite32(HDLCD_REG_COMMAND, HDLCD_ENABLE);
+
+  return EFI_SUCCESS;
+}
+
+VOID
+LcdShutdown (
+  VOID
+  )
+{
+  // Disable the controller
+  MmioWrite32 (HDLCD_REG_COMMAND, HDLCD_DISABLE);
+}
+
+EFI_STATUS
+LcdIdentify (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
diff --git a/Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/HdLcdGraphicsOutputDxe.inf b/Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/HdLcdGraphicsOutputDxe.inf
new file mode 100644
index 000000000000..34e12987038e
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/HdLcdGraphicsOutputDxe.inf
@@ -0,0 +1,63 @@ 
+#/** @file
+#
+#  Component description file for HDLCD module
+#
+#  Copyright (c) 2011-2012, 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                      = HdLcdGraphicsDxe
+  FILE_GUID                      = ce660500-824d-11e0-ac72-0002a5d5c51b
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = LcdGraphicsOutputDxeInitialize
+
+[Sources.common]
+  LcdGraphicsOutputDxe.c
+  LcdGraphicsOutputBlt.c
+  HdLcd.c
+
+[Packages]
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  ArmPkg/ArmPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  Platform/ARM/VExpressPkg/ArmVExpressPkg.dec
+
+[LibraryClasses]
+  ArmLib
+  UefiLib
+  BaseLib
+  DebugLib
+  TimerLib
+  UefiDriverEntryPoint
+  UefiBootServicesTableLib
+  IoLib
+  BaseMemoryLib
+  LcdPlatformLib
+
+[Protocols]
+  gEfiDevicePathProtocolGuid
+  gEfiGraphicsOutputProtocolGuid                # Produced
+  gEfiEdidDiscoveredProtocolGuid                # Produced
+  gEfiEdidActiveProtocolGuid                    # Produced
+  gEfiEdidOverrideProtocolGuid                  # Produced
+
+[FixedPcd]
+  gArmPlatformTokenSpaceGuid.PcdArmHdLcdBase
+
+[FeaturePcd]
+  gArmPlatformTokenSpaceGuid.PcdGopDisableOnExitBootServices
+
+[Depex]
+  gEfiCpuArchProtocolGuid
diff --git a/Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputBlt.c b/Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputBlt.c
new file mode 100644
index 000000000000..77f93cbb675e
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputBlt.c
@@ -0,0 +1,882 @@ 
+/** @file
+
+ Copyright (c) 2011-2013, 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/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <Guid/GlobalVariable.h>
+
+#include "LcdGraphicsOutputDxe.h"
+
+extern BOOLEAN mDisplayInitialized;
+
+//
+// Function Definitions
+//
+
+STATIC
+EFI_STATUS
+VideoCopyNoHorizontalOverlap (
+  IN UINTN          BitsPerPixel,
+  IN volatile VOID  *FrameBufferBase,
+  IN UINT32         HorizontalResolution,
+  IN UINTN          SourceX,
+  IN UINTN          SourceY,
+  IN UINTN          DestinationX,
+  IN UINTN          DestinationY,
+  IN UINTN          Width,
+  IN UINTN          Height
+)
+{
+  EFI_STATUS    Status = EFI_SUCCESS;
+  UINTN         SourceLine;
+  UINTN         DestinationLine;
+  UINTN         WidthInBytes;
+  UINTN         LineCount;
+  INTN          Step;
+  VOID          *SourceAddr;
+  VOID          *DestinationAddr;
+
+  if( DestinationY <= SourceY ) {
+    // scrolling up (or horizontally but without overlap)
+    SourceLine       = SourceY;
+    DestinationLine  = DestinationY;
+    Step             = 1;
+  } else {
+    // scrolling down
+    SourceLine       = SourceY + Height;
+    DestinationLine  = DestinationY + Height;
+    Step             = -1;
+  }
+
+  switch (BitsPerPixel) {
+
+  case LCD_BITS_PER_PIXEL_24:
+
+    WidthInBytes = Width * 4;
+
+    for( LineCount = 0; LineCount < Height; LineCount++ ) {
+      // Update the start addresses of source & destination using 32bit pointer arithmetic
+      SourceAddr      = (VOID *)((UINT32 *)FrameBufferBase + SourceLine      * HorizontalResolution + SourceX     );
+      DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX);
+
+      // Copy the entire line Y from video ram to the temp buffer
+      CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
+
+      // Update the line numbers
+      SourceLine      += Step;
+      DestinationLine += Step;
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_16_555:
+  case LCD_BITS_PER_PIXEL_16_565:
+  case LCD_BITS_PER_PIXEL_12_444:
+
+    WidthInBytes = Width * 2;
+
+    for( LineCount = 0; LineCount < Height; LineCount++ ) {
+      // Update the start addresses of source & destination using 16bit pointer arithmetic
+      SourceAddr      = (VOID *)((UINT16 *)FrameBufferBase + SourceLine      * HorizontalResolution + SourceX     );
+      DestinationAddr = (VOID *)((UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationX);
+
+      // Copy the entire line Y from video ram to the temp buffer
+      CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
+
+      // Update the line numbers
+      SourceLine      += Step;
+      DestinationLine += Step;
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_8:
+  case LCD_BITS_PER_PIXEL_4:
+  case LCD_BITS_PER_PIXEL_2:
+  case LCD_BITS_PER_PIXEL_1:
+  default:
+    // Can't handle this case
+    DEBUG((DEBUG_ERROR, "ArmVeGraphics_Blt: EfiBltVideoToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
+    Status = EFI_INVALID_PARAMETER;
+    goto EXIT;
+    // break;
+
+  }
+
+  EXIT:
+  return Status;
+}
+
+STATIC
+EFI_STATUS
+VideoCopyHorizontalOverlap (
+  IN UINTN          BitsPerPixel,
+  IN volatile VOID  *FrameBufferBase,
+  UINT32            HorizontalResolution,
+  IN UINTN          SourceX,
+  IN UINTN          SourceY,
+  IN UINTN          DestinationX,
+  IN UINTN          DestinationY,
+  IN UINTN          Width,
+  IN UINTN          Height
+)
+{
+  EFI_STATUS      Status = EFI_SUCCESS;
+
+  UINT32 *PixelBuffer32bit;
+  UINT32 *SourcePixel32bit;
+  UINT32 *DestinationPixel32bit;
+
+  UINT16 *PixelBuffer16bit;
+  UINT16 *SourcePixel16bit;
+  UINT16 *DestinationPixel16bit;
+
+  UINT32          SourcePixelY;
+  UINT32          DestinationPixelY;
+  UINTN           SizeIn32Bits;
+  UINTN           SizeIn16Bits;
+
+  switch (BitsPerPixel) {
+
+  case LCD_BITS_PER_PIXEL_24:
+    // Allocate a temporary buffer
+
+    PixelBuffer32bit = (UINT32 *) AllocatePool((Height * Width) * sizeof(UINT32));
+
+    if (PixelBuffer32bit == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto EXIT;
+    }
+
+    SizeIn32Bits = Width * 4;
+
+    // Copy from the video ram (source region) to a temp buffer
+    for (SourcePixelY = SourceY, DestinationPixel32bit = PixelBuffer32bit;
+         SourcePixelY < SourceY + Height;
+         SourcePixelY++, DestinationPixel32bit += Width)
+    {
+      // Update the start address of line Y (source)
+      SourcePixel32bit = (UINT32 *)FrameBufferBase + SourcePixelY * HorizontalResolution + SourceX;
+
+      // Copy the entire line Y from video ram to the temp buffer
+      CopyMem( (VOID *)DestinationPixel32bit, (CONST VOID *)SourcePixel32bit, SizeIn32Bits);
+    }
+
+    // Copy from the temp buffer to the video ram (destination region)
+    for (DestinationPixelY = DestinationY, SourcePixel32bit = PixelBuffer32bit;
+         DestinationPixelY < DestinationY + Height;
+         DestinationPixelY++, SourcePixel32bit += Width)
+    {
+      // Update the start address of line Y (target)
+      DestinationPixel32bit = (UINT32 *)FrameBufferBase + DestinationPixelY * HorizontalResolution + DestinationX;
+
+      // Copy the entire line Y from the temp buffer to video ram
+      CopyMem( (VOID *)DestinationPixel32bit, (CONST VOID *)SourcePixel32bit, SizeIn32Bits);
+    }
+
+    // Free up the allocated memory
+    FreePool((VOID *) PixelBuffer32bit);
+
+    break;
+
+
+  case LCD_BITS_PER_PIXEL_16_555:
+  case LCD_BITS_PER_PIXEL_16_565:
+  case LCD_BITS_PER_PIXEL_12_444:
+    // Allocate a temporary buffer
+    PixelBuffer16bit = (UINT16 *) AllocatePool((Height * Width) * sizeof(UINT16));
+
+    if (PixelBuffer16bit == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto EXIT;
+    }
+
+    // Access each pixel inside the source area of the Video Memory and copy it to the temp buffer
+
+    SizeIn16Bits = Width * 2;
+
+    for (SourcePixelY = SourceY, DestinationPixel16bit = PixelBuffer16bit;
+         SourcePixelY < SourceY + Height;
+         SourcePixelY++, DestinationPixel16bit += Width)
+    {
+      // Calculate the source address:
+      SourcePixel16bit = (UINT16 *)FrameBufferBase + SourcePixelY * HorizontalResolution + SourceX;
+
+      // Copy the entire line Y from Video to the temp buffer
+      CopyMem( (VOID *)DestinationPixel16bit, (CONST VOID *)SourcePixel16bit, SizeIn16Bits);
+    }
+
+    // Copy from the temp buffer into the destination area of the Video Memory
+
+    for (DestinationPixelY = DestinationY, SourcePixel16bit = PixelBuffer16bit;
+         DestinationPixelY < DestinationY + Height;
+         DestinationPixelY++, SourcePixel16bit += Width)
+    {
+      // Calculate the target address:
+      DestinationPixel16bit = (UINT16 *)FrameBufferBase + (DestinationPixelY * HorizontalResolution + DestinationX);
+
+      // Copy the entire line Y from the temp buffer to Video
+      CopyMem( (VOID *)DestinationPixel16bit, (CONST VOID *)SourcePixel16bit, SizeIn16Bits);
+    }
+
+    // Free the allocated memory
+    FreePool((VOID *) PixelBuffer16bit);
+
+    break;
+
+
+  case LCD_BITS_PER_PIXEL_8:
+  case LCD_BITS_PER_PIXEL_4:
+  case LCD_BITS_PER_PIXEL_2:
+  case LCD_BITS_PER_PIXEL_1:
+  default:
+    // Can't handle this case
+    DEBUG((DEBUG_ERROR, "ArmVeGraphics_Blt: EfiBltVideoToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
+    Status = EFI_INVALID_PARAMETER;
+    goto EXIT;
+    // break;
+
+  }
+
+EXIT:
+  return Status;
+}
+
+STATIC
+EFI_STATUS
+BltVideoFill (
+  IN EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,
+  IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *EfiSourcePixel,     OPTIONAL
+  IN UINTN                               SourceX,
+  IN UINTN                               SourceY,
+  IN UINTN                               DestinationX,
+  IN UINTN                               DestinationY,
+  IN UINTN                               Width,
+  IN UINTN                               Height,
+  IN UINTN                               Delta           OPTIONAL   // Number of BYTES in a row of the BltBuffer
+  )
+{
+  EFI_PIXEL_BITMASK*  PixelInformation;
+  EFI_STATUS         Status;
+  UINT32             HorizontalResolution;
+  LCD_BPP            BitsPerPixel;
+  VOID            *FrameBufferBase;
+  VOID            *DestinationAddr;
+  UINT16          *DestinationPixel16bit;
+  UINT16          Pixel16bit;
+  UINT32          DestinationPixelX;
+  UINT32          DestinationLine;
+  UINTN           WidthInBytes;
+
+  Status           = EFI_SUCCESS;
+  PixelInformation = &This->Mode->Info->PixelInformation;
+  FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
+  HorizontalResolution = This->Mode->Info->HorizontalResolution;
+
+  LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
+
+  switch (BitsPerPixel) {
+  case LCD_BITS_PER_PIXEL_24:
+    WidthInBytes = Width * 4;
+
+    // Copy the SourcePixel into every pixel inside the target rectangle
+    for (DestinationLine = DestinationY;
+         DestinationLine < DestinationY + Height;
+         DestinationLine++)
+    {
+      // Calculate the target address using 32bit pointer arithmetic:
+      DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution  + DestinationX);
+
+      // Fill the entire line
+      SetMem32 (DestinationAddr, WidthInBytes, *((UINT32 *)EfiSourcePixel));
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_16_555:
+    // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel
+    Pixel16bit = (UINT16) (
+        ( (EfiSourcePixel->Red      <<  7) & PixelInformation->RedMask      )
+      | ( (EfiSourcePixel->Green    <<  2) & PixelInformation->GreenMask    )
+      | ( (EfiSourcePixel->Blue     >>  3) & PixelInformation->BlueMask     )
+//      | ( 0                           & PixelInformation->ReservedMask )
+     );
+
+    // Copy the SourcePixel into every pixel inside the target rectangle
+    for (DestinationLine = DestinationY;
+         DestinationLine < DestinationY + Height;
+         DestinationLine++)
+    {
+      for (DestinationPixelX = DestinationX;
+           DestinationPixelX < DestinationX + Width;
+           DestinationPixelX++)
+      {
+        // Calculate the target address:
+        DestinationPixel16bit =  (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
+
+        // Copy the pixel into the new target
+        *DestinationPixel16bit = Pixel16bit;
+      }
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_16_565:
+    // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel
+    Pixel16bit = (UINT16) (
+        ( (EfiSourcePixel->Red      <<  8) & PixelInformation->RedMask      )
+      | ( (EfiSourcePixel->Green    <<  3) & PixelInformation->GreenMask    )
+      | ( (EfiSourcePixel->Blue     >>  3) & PixelInformation->BlueMask     )
+     );
+
+    // Copy the SourcePixel into every pixel inside the target rectangle
+    for (DestinationLine = DestinationY;
+         DestinationLine < DestinationY + Height;
+         DestinationLine++)
+    {
+      for (DestinationPixelX = DestinationX;
+           DestinationPixelX < DestinationX + Width;
+           DestinationPixelX++)
+      {
+        // Calculate the target address:
+        DestinationPixel16bit =  (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution  + DestinationPixelX;
+
+        // Copy the pixel into the new target
+        *DestinationPixel16bit = Pixel16bit;
+      }
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_12_444:
+    // Convert the EFI pixel at the start of the BltBuffer(0,0) into a video display pixel
+    Pixel16bit = (UINT16) (
+        ( (EfiSourcePixel->Red      >> 4) & PixelInformation->RedMask      )
+      | ( (EfiSourcePixel->Green        ) & PixelInformation->GreenMask    )
+      | ( (EfiSourcePixel->Blue     << 4) & PixelInformation->BlueMask     )
+     );
+
+    // Copy the SourcePixel into every pixel inside the target rectangle
+    for (DestinationLine = DestinationY;
+         DestinationLine < DestinationY + Height;
+         DestinationLine++)
+    {
+      for (DestinationPixelX = DestinationX;
+           DestinationPixelX < DestinationX + Width;
+           DestinationPixelX++)
+      {
+        // Calculate the target address:
+        DestinationPixel16bit =  (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution  + DestinationPixelX;
+
+        // Copy the pixel into the new target
+        *DestinationPixel16bit = Pixel16bit;
+      }
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_8:
+  case LCD_BITS_PER_PIXEL_4:
+  case LCD_BITS_PER_PIXEL_2:
+  case LCD_BITS_PER_PIXEL_1:
+  default:
+    // Can't handle this case
+    DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltVideoFill: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
+    Status = EFI_INVALID_PARAMETER;
+    break;
+  }
+
+  return Status;
+}
+
+STATIC
+EFI_STATUS
+BltVideoToBltBuffer (
+  IN EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,
+  IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *BltBuffer,     OPTIONAL
+  IN UINTN                               SourceX,
+  IN UINTN                               SourceY,
+  IN UINTN                               DestinationX,
+  IN UINTN                               DestinationY,
+  IN UINTN                               Width,
+  IN UINTN                               Height,
+  IN UINTN                               Delta           OPTIONAL   // Number of BYTES in a row of the BltBuffer
+  )
+{
+  EFI_STATUS         Status;
+  UINT32             HorizontalResolution;
+  LCD_BPP            BitsPerPixel;
+  EFI_PIXEL_BITMASK  *PixelInformation;
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiDestinationPixel;
+  VOID   *FrameBufferBase;
+  VOID            *SourceAddr;
+  VOID            *DestinationAddr;
+  UINT16 *SourcePixel16bit;
+  UINT16          Pixel16bit;
+  UINT32          SourcePixelX;
+  UINT32          SourceLine;
+  UINT32          DestinationPixelX;
+  UINT32          DestinationLine;
+  UINT32          BltBufferHorizontalResolution;
+  UINTN           WidthInBytes;
+
+  Status = EFI_SUCCESS;
+  PixelInformation = &This->Mode->Info->PixelInformation;
+  HorizontalResolution = This->Mode->Info->HorizontalResolution;
+  FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
+
+  if(( Delta != 0 ) && ( Delta != Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
+    // Delta is not zero and it is different from the width.
+    // Divide it by the size of a pixel to find out the buffer's horizontal resolution.
+    BltBufferHorizontalResolution = (UINT32) (Delta / sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+  } else {
+    BltBufferHorizontalResolution = Width;
+  }
+
+  LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
+
+  switch (BitsPerPixel) {
+  case LCD_BITS_PER_PIXEL_24:
+    WidthInBytes = Width * 4;
+
+    // Access each line inside the Video Memory
+    for (SourceLine = SourceY, DestinationLine = DestinationY;
+         SourceLine < SourceY + Height;
+         SourceLine++, DestinationLine++)
+    {
+      // Calculate the source and target addresses using 32bit pointer arithmetic:
+      SourceAddr      = (VOID *)((UINT32 *)FrameBufferBase + SourceLine      * HorizontalResolution          + SourceX     );
+      DestinationAddr = (VOID *)((UINT32 *)BltBuffer       + DestinationLine * BltBufferHorizontalResolution + DestinationX);
+
+      // Copy the entire line
+      CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_16_555:
+    // Access each pixel inside the Video Memory
+    for (SourceLine = SourceY, DestinationLine = DestinationY;
+         SourceLine < SourceY + Height;
+         SourceLine++, DestinationLine++)
+    {
+      for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
+           SourcePixelX < SourceX + Width;
+           SourcePixelX++, DestinationPixelX++)
+      {
+        // Calculate the source and target addresses:
+        SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX;
+        EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX;
+
+        // Snapshot the pixel from the video buffer once, to speed up the operation.
+        // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.
+        Pixel16bit = *SourcePixel16bit;
+
+        // Copy the pixel into the new target
+        EfiDestinationPixel->Red      = (UINT8) ( (Pixel16bit & PixelInformation->RedMask     ) >>  7 );
+        EfiDestinationPixel->Green    = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask   ) >>  2);
+        EfiDestinationPixel->Blue     = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask    ) <<  3 );
+        // EfiDestinationPixel->Reserved = (UINT8) 0;
+      }
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_16_565:
+    // Access each pixel inside the Video Memory
+    for (SourceLine = SourceY, DestinationLine = DestinationY;
+         SourceLine < SourceY + Height;
+         SourceLine++, DestinationLine++)
+    {
+      for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
+           SourcePixelX < SourceX + Width;
+           SourcePixelX++, DestinationPixelX++)
+      {
+        // Calculate the source and target addresses:
+        SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX;
+        EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX;
+
+        // Snapshot the pixel from the video buffer once, to speed up the operation.
+        // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.
+        Pixel16bit = *SourcePixel16bit;
+
+        // Copy the pixel into the new target
+        // There is no info for the Reserved byte, so we set it to zero
+        EfiDestinationPixel->Red      = (UINT8) ( (Pixel16bit & PixelInformation->RedMask     ) >> 8 );
+        EfiDestinationPixel->Green    = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask   ) >> 3);
+        EfiDestinationPixel->Blue     = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask    ) << 3 );
+        // EfiDestinationPixel->Reserved = (UINT8) 0;
+      }
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_12_444:
+    // Access each pixel inside the Video Memory
+    for (SourceLine = SourceY, DestinationLine = DestinationY;
+         SourceLine < SourceY + Height;
+         SourceLine++, DestinationLine++)
+    {
+      for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
+           SourcePixelX < SourceX + Width;
+           SourcePixelX++, DestinationPixelX++)
+      {
+        // Calculate the source and target addresses:
+        SourcePixel16bit = (UINT16 *)FrameBufferBase + SourceLine * HorizontalResolution + SourcePixelX;
+        EfiDestinationPixel = BltBuffer + DestinationLine * BltBufferHorizontalResolution + DestinationPixelX;
+
+        // Snapshot the pixel from the video buffer once, to speed up the operation.
+        // If we were dereferencing the pointer, as it is volatile, we would perform 3 memory read operations.
+        Pixel16bit = *SourcePixel16bit;
+
+        // Copy the pixel into the new target
+        EfiDestinationPixel->Red      = (UINT8) ( (Pixel16bit & PixelInformation->RedMask     ) >> 4 );
+        EfiDestinationPixel->Green    = (UINT8) ( (Pixel16bit & PixelInformation->GreenMask   )     );
+        EfiDestinationPixel->Blue     = (UINT8) ( (Pixel16bit & PixelInformation->BlueMask    ) << 4 );
+        // EfiDestinationPixel->Reserved = (UINT8) 0;
+      }
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_8:
+  case LCD_BITS_PER_PIXEL_4:
+  case LCD_BITS_PER_PIXEL_2:
+  case LCD_BITS_PER_PIXEL_1:
+  default:
+    // Can't handle this case
+    DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltVideoToBltBuffer: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
+    Status = EFI_INVALID_PARAMETER;
+    break;
+  }
+  return Status;
+}
+
+STATIC
+EFI_STATUS
+BltBufferToVideo (
+  IN EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,
+  IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *BltBuffer,     OPTIONAL
+  IN UINTN                               SourceX,
+  IN UINTN                               SourceY,
+  IN UINTN                               DestinationX,
+  IN UINTN                               DestinationY,
+  IN UINTN                               Width,
+  IN UINTN                               Height,
+  IN UINTN                               Delta           OPTIONAL   // Number of BYTES in a row of the BltBuffer
+  )
+{
+  EFI_STATUS         Status;
+  UINT32             HorizontalResolution;
+  LCD_BPP            BitsPerPixel;
+  EFI_PIXEL_BITMASK  *PixelInformation;
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *EfiSourcePixel;
+  VOID   *FrameBufferBase;
+  VOID            *SourceAddr;
+  VOID            *DestinationAddr;
+  UINT16 *DestinationPixel16bit;
+  UINT32          SourcePixelX;
+  UINT32          SourceLine;
+  UINT32          DestinationPixelX;
+  UINT32          DestinationLine;
+  UINT32          BltBufferHorizontalResolution;
+  UINTN           WidthInBytes;
+
+  Status = EFI_SUCCESS;
+  PixelInformation = &This->Mode->Info->PixelInformation;
+  HorizontalResolution = This->Mode->Info->HorizontalResolution;
+  FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
+
+  if(( Delta != 0 ) && ( Delta != Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
+    // Delta is not zero and it is different from the width.
+    // Divide it by the size of a pixel to find out the buffer's horizontal resolution.
+    BltBufferHorizontalResolution = (UINT32) (Delta / sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+  } else {
+    BltBufferHorizontalResolution = Width;
+  }
+
+  LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
+
+  switch (BitsPerPixel) {
+  case LCD_BITS_PER_PIXEL_24:
+    WidthInBytes = Width * 4;
+
+    // Access each pixel inside the BltBuffer Memory
+    for (SourceLine = SourceY, DestinationLine = DestinationY;
+       SourceLine < SourceY + Height;
+       SourceLine++, DestinationLine++)
+    {
+      // Calculate the source and target addresses using 32bit pointer arithmetic:
+      SourceAddr      = (VOID *)((UINT32 *)BltBuffer       + SourceLine      * BltBufferHorizontalResolution + SourceX     );
+      DestinationAddr = (VOID *)((UINT32 *)FrameBufferBase + DestinationLine * HorizontalResolution          + DestinationX);
+
+      // Copy the entire row Y
+      CopyMem( DestinationAddr, SourceAddr, WidthInBytes);
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_16_555:
+    // Access each pixel inside the BltBuffer Memory
+    for (SourceLine = SourceY, DestinationLine = DestinationY;
+       SourceLine < SourceY + Height;
+       SourceLine++, DestinationLine++) {
+
+      for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
+           SourcePixelX < SourceX + Width;
+           SourcePixelX++, DestinationPixelX++)
+      {
+        // Calculate the source and target addresses:
+        EfiSourcePixel  = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX;
+        DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
+
+        // Copy the pixel into the new target
+        // Only the most significant bits will be copied across:
+        // To convert from 8 bits to 5 bits per pixel we throw away the 3 least significant bits
+        *DestinationPixel16bit = (UINT16) (
+              ( (EfiSourcePixel->Red      <<  7) & PixelInformation->RedMask      )
+            | ( (EfiSourcePixel->Green    <<  2) & PixelInformation->GreenMask    )
+            | ( (EfiSourcePixel->Blue     >>  3) & PixelInformation->BlueMask     )
+      //            | ( 0                                & PixelInformation->ReservedMask )
+            );
+      }
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_16_565:
+    // Access each pixel inside the BltBuffer Memory
+    for (SourceLine = SourceY, DestinationLine = DestinationY;
+         SourceLine < SourceY + Height;
+         SourceLine++, DestinationLine++) {
+
+      for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
+           SourcePixelX < SourceX + Width;
+           SourcePixelX++, DestinationPixelX++)
+      {
+        // Calculate the source and target addresses:
+        EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX;
+        DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
+
+        // Copy the pixel into the new target
+        // Only the most significant bits will be copied across:
+        // To convert from 8 bits to 5 or 6 bits per pixel we throw away the 3 or 2  least significant bits
+        // There is no room for the Reserved byte so we ignore that completely
+        *DestinationPixel16bit = (UINT16) (
+              ( (EfiSourcePixel->Red      <<  8) & PixelInformation->RedMask      )
+            | ( (EfiSourcePixel->Green    <<  3) & PixelInformation->GreenMask    )
+            | ( (EfiSourcePixel->Blue     >>  3) & PixelInformation->BlueMask     )
+           );
+      }
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_12_444:
+    // Access each pixel inside the BltBuffer Memory
+    for (SourceLine = SourceY, DestinationLine = DestinationY;
+         SourceLine < SourceY + Height;
+         SourceLine++, DestinationLine++) {
+
+      for (SourcePixelX = SourceX, DestinationPixelX = DestinationX;
+           SourcePixelX < SourceX + Width;
+           SourcePixelX++, DestinationPixelX++)
+      {
+        // Calculate the source and target addresses:
+        EfiSourcePixel = BltBuffer + SourceLine * BltBufferHorizontalResolution + SourcePixelX;
+        DestinationPixel16bit = (UINT16 *)FrameBufferBase + DestinationLine * HorizontalResolution + DestinationPixelX;
+
+        // Copy the pixel into the new target
+        // Only the most significant bits will be copied across:
+        // To convert from 8 bits to 5 bits per pixel we throw away the 3 least significant bits
+        *DestinationPixel16bit = (UINT16) (
+              ( (EfiSourcePixel->Red      << 4) & PixelInformation->RedMask      )
+            | ( (EfiSourcePixel->Green        ) & PixelInformation->GreenMask    )
+            | ( (EfiSourcePixel->Blue     >> 4) & PixelInformation->BlueMask     )
+  //            | ( 0                               & PixelInformation->ReservedMask )
+           );
+      }
+    }
+    break;
+
+  case LCD_BITS_PER_PIXEL_8:
+  case LCD_BITS_PER_PIXEL_4:
+  case LCD_BITS_PER_PIXEL_2:
+  case LCD_BITS_PER_PIXEL_1:
+  default:
+    // Can't handle this case
+    DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: EfiBltBufferToVideo: INVALID Number of Bits Per Pixel: %d\n", BitsPerPixel));
+    Status = EFI_INVALID_PARAMETER;
+    break;
+  }
+  return Status;
+}
+
+STATIC
+EFI_STATUS
+BltVideoToVideo (
+  IN EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,
+  IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *BltBuffer,     OPTIONAL
+  IN UINTN                               SourceX,
+  IN UINTN                               SourceY,
+  IN UINTN                               DestinationX,
+  IN UINTN                               DestinationY,
+  IN UINTN                               Width,
+  IN UINTN                               Height,
+  IN UINTN                               Delta           OPTIONAL   // Number of BYTES in a row of the BltBuffer
+  )
+{
+  EFI_STATUS         Status;
+  UINT32             HorizontalResolution;
+  LCD_BPP            BitsPerPixel;
+  VOID   *FrameBufferBase;
+
+  HorizontalResolution = This->Mode->Info->HorizontalResolution;
+  FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
+
+  //
+  // BltVideo to BltVideo:
+  //
+  //  Source is the Video Memory,
+  //  Destination is the Video Memory
+
+  LcdPlatformGetBpp (This->Mode->Mode,&BitsPerPixel);
+  FrameBufferBase = (UINTN *)((UINTN)(This->Mode->FrameBufferBase));
+
+  // The UEFI spec currently states:
+  // "There is no limitation on the overlapping of the source and destination rectangles"
+  // Therefore, we must be careful to avoid overwriting the source data
+  if( SourceY == DestinationY ) {
+    // Copying within the same height, e.g. horizontal shift
+    if( SourceX == DestinationX ) {
+      // Nothing to do
+      Status = EFI_SUCCESS;
+    } else if( ((SourceX>DestinationX)?(SourceX - DestinationX):(DestinationX - SourceX)) < Width ) {
+      // There is overlap
+      Status = VideoCopyHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );
+    } else {
+      // No overlap
+      Status = VideoCopyNoHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );
+    }
+  } else {
+    // Copying from different heights
+    Status = VideoCopyNoHorizontalOverlap (BitsPerPixel, FrameBufferBase, HorizontalResolution, SourceX, SourceY, DestinationX, DestinationY, Width, Height );
+  }
+
+  return Status;
+}
+
+/***************************************
+ * GraphicsOutput Protocol function, mapping to
+ * EFI_GRAPHICS_OUTPUT_PROTOCOL.Blt
+ *
+ * PRESUMES: 1 pixel = 4 bytes (32bits)
+ *  ***************************************/
+EFI_STATUS
+EFIAPI
+LcdGraphicsBlt (
+  IN EFI_GRAPHICS_OUTPUT_PROTOCOL        *This,
+  IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *BltBuffer,     OPTIONAL
+  IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION   BltOperation,
+  IN UINTN                               SourceX,
+  IN UINTN                               SourceY,
+  IN UINTN                               DestinationX,
+  IN UINTN                               DestinationY,
+  IN UINTN                               Width,
+  IN UINTN                               Height,
+  IN UINTN                               Delta           OPTIONAL   // Number of BYTES in a row of the BltBuffer
+  )
+{
+  EFI_STATUS         Status;
+  UINT32             HorizontalResolution;
+  UINT32             VerticalResolution;
+  LCD_INSTANCE*      Instance;
+
+  Instance = LCD_INSTANCE_FROM_GOP_THIS(This);
+
+  // Setup the hardware if not already done
+  if (!mDisplayInitialized) {
+    Status = InitializeDisplay (Instance);
+    if (EFI_ERROR(Status)) {
+      goto EXIT;
+    }
+  }
+
+  HorizontalResolution = This->Mode->Info->HorizontalResolution;
+  VerticalResolution   = This->Mode->Info->VerticalResolution;
+
+  DEBUG((DEBUG_INFO, "LcdGraphicsBlt (BltOperation:%d,DestX:%d,DestY:%d,Width:%d,Height:%d) res(%d,%d)\n",
+      BltOperation,DestinationX,DestinationY,Width,Height,HorizontalResolution,VerticalResolution));
+
+  // Check we have reasonable parameters
+  if (Width == 0 || Height == 0) {
+    DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: ERROR - Invalid dimension: Zero size area.\n" ));
+    Status = EFI_INVALID_PARAMETER;
+    goto EXIT;
+  }
+
+  if ((BltOperation == EfiBltVideoFill) || (BltOperation == EfiBltBufferToVideo) || (BltOperation == EfiBltVideoToBltBuffer)) {
+    ASSERT( BltBuffer != NULL);
+  }
+
+  /*if ((DestinationX >= HorizontalResolution) || (DestinationY >= VerticalResolution)) {
+    DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: ERROR - Invalid destination.\n" ));
+    Status = EFI_INVALID_PARAMETER;
+    goto EXIT;
+  }*/
+
+  // If we are reading data out of the video buffer, check that the source area is within the display limits
+  if ((BltOperation == EfiBltVideoToBltBuffer) || (BltOperation == EfiBltVideoToVideo)) {
+    if ((SourceY + Height > VerticalResolution) || (SourceX + Width > HorizontalResolution)) {
+      DEBUG((DEBUG_INFO, "LcdGraphicsBlt: ERROR - Invalid source resolution.\n" ));
+      DEBUG((DEBUG_INFO, "                      - SourceY=%d + Height=%d > VerticalResolution=%d.\n", SourceY, Height, VerticalResolution ));
+      DEBUG((DEBUG_INFO, "                      - SourceX=%d + Width=%d > HorizontalResolution=%d.\n", SourceX, Width, HorizontalResolution ));
+      Status = EFI_INVALID_PARAMETER;
+      goto EXIT;
+    }
+  }
+
+  // If we are writing data into the video buffer, that the destination area is within the display limits
+  if ((BltOperation == EfiBltVideoFill) || (BltOperation == EfiBltBufferToVideo) || (BltOperation == EfiBltVideoToVideo)) {
+    if ((DestinationY + Height > VerticalResolution) || (DestinationX + Width > HorizontalResolution)) {
+      DEBUG((DEBUG_INFO, "LcdGraphicsBlt: ERROR - Invalid destination resolution.\n" ));
+      DEBUG((DEBUG_INFO, "                      - DestinationY=%d + Height=%d > VerticalResolution=%d.\n", DestinationY, Height, VerticalResolution ));
+      DEBUG((DEBUG_INFO, "                      - DestinationX=%d + Width=%d > HorizontalResolution=%d.\n", DestinationX, Width, HorizontalResolution ));
+      Status = EFI_INVALID_PARAMETER;
+      goto EXIT;
+    }
+  }
+
+  //
+  // Perform the Block Transfer Operation
+  //
+
+  switch (BltOperation) {
+  case EfiBltVideoFill:
+    Status = BltVideoFill (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
+    break;
+
+  case EfiBltVideoToBltBuffer:
+    Status = BltVideoToBltBuffer (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
+    break;
+
+  case EfiBltBufferToVideo:
+    Status = BltBufferToVideo (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
+    break;
+
+  case EfiBltVideoToVideo:
+    Status = BltVideoToVideo (This, BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta);
+    break;
+
+  case EfiGraphicsOutputBltOperationMax:
+  default:
+    DEBUG((DEBUG_ERROR, "LcdGraphicsBlt: Invalid Operation\n"));
+    Status = EFI_INVALID_PARAMETER;
+    break;
+  }
+
+EXIT:
+  return Status;
+}
diff --git a/Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.c b/Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.c
new file mode 100644
index 000000000000..b721061fc1df
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.c
@@ -0,0 +1,393 @@ 
+/** @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/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <Guid/GlobalVariable.h>
+
+#include "LcdGraphicsOutputDxe.h"
+
+/**********************************************************************
+ *
+ *  This file implements the Graphics Output protocol on ArmVersatileExpress
+ *  using the Lcd controller
+ *
+ **********************************************************************/
+
+//
+// Global variables
+//
+
+BOOLEAN mDisplayInitialized = FALSE;
+
+LCD_INSTANCE mLcdTemplate = {
+  LCD_INSTANCE_SIGNATURE,
+  NULL, // Handle
+  { // ModeInfo
+    0, // Version
+    0, // HorizontalResolution
+    0, // VerticalResolution
+    PixelBltOnly, // PixelFormat
+    { 0 }, // PixelInformation
+    0, // PixelsPerScanLine
+  },
+  {
+    0, // MaxMode;
+    0, // Mode;
+    NULL, // Info;
+    0, // SizeOfInfo;
+    0, // FrameBufferBase;
+    0 // FrameBufferSize;
+  },
+  { // Gop
+    LcdGraphicsQueryMode,  // QueryMode
+    LcdGraphicsSetMode,    // SetMode
+    LcdGraphicsBlt,        // Blt
+    NULL                     // *Mode
+  },
+  { // DevicePath
+    {
+      {
+        HARDWARE_DEVICE_PATH, HW_VENDOR_DP,
+        { (UINT8) (sizeof(VENDOR_DEVICE_PATH)), (UINT8) ((sizeof(VENDOR_DEVICE_PATH)) >> 8) },
+      },
+      // Hardware Device Path for Lcd
+      EFI_CALLER_ID_GUID // Use the driver's GUID
+    },
+
+    {
+      END_DEVICE_PATH_TYPE,
+      END_ENTIRE_DEVICE_PATH_SUBTYPE,
+      { sizeof(EFI_DEVICE_PATH_PROTOCOL), 0 }
+    }
+  },
+  (EFI_EVENT) NULL // ExitBootServicesEvent
+};
+
+EFI_STATUS
+LcdInstanceContructor (
+  OUT LCD_INSTANCE** NewInstance
+  )
+{
+  LCD_INSTANCE* Instance;
+
+  Instance = AllocateCopyPool (sizeof(LCD_INSTANCE), &mLcdTemplate);
+  if (Instance == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Instance->Gop.Mode          = &Instance->Mode;
+  Instance->Gop.Mode->MaxMode = LcdPlatformGetMaxMode ();
+  Instance->Mode.Info         = &Instance->ModeInfo;
+
+  *NewInstance = Instance;
+  return EFI_SUCCESS;
+}
+
+//
+// Function Definitions
+//
+
+EFI_STATUS
+InitializeDisplay (
+  IN LCD_INSTANCE* Instance
+  )
+{
+  EFI_STATUS             Status = EFI_SUCCESS;
+  EFI_PHYSICAL_ADDRESS   VramBaseAddress;
+  UINTN                  VramSize;
+
+  Status = LcdPlatformGetVram (&VramBaseAddress, &VramSize);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  // Setup the LCD
+  Status = LcdInitialize (VramBaseAddress);
+  if (EFI_ERROR(Status)) {
+    goto EXIT_ERROR_LCD_SHUTDOWN;
+  }
+
+  Status = LcdPlatformInitializeDisplay (Instance->Handle);
+  if (EFI_ERROR(Status)) {
+    goto EXIT_ERROR_LCD_SHUTDOWN;
+  }
+
+  // Setup all the relevant mode information
+  Instance->Gop.Mode->SizeOfInfo      = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+  Instance->Gop.Mode->FrameBufferBase = VramBaseAddress;
+
+  // Set the flag before changing the mode, to avoid infinite loops
+  mDisplayInitialized = TRUE;
+
+  // All is ok, so don't deal with any errors
+  goto EXIT;
+
+EXIT_ERROR_LCD_SHUTDOWN:
+  DEBUG((DEBUG_ERROR, "InitializeDisplay: ERROR - Can not initialise the display. Exit Status=%r\n", Status));
+  LcdShutdown ();
+
+EXIT:
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+LcdGraphicsOutputDxeInitialize (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS  Status = EFI_SUCCESS;
+  LCD_INSTANCE* Instance;
+
+  Status = LcdIdentify ();
+  if (EFI_ERROR(Status)) {
+    goto EXIT;
+  }
+
+  Status = LcdInstanceContructor (&Instance);
+  if (EFI_ERROR(Status)) {
+    goto EXIT;
+  }
+
+  // Install the Graphics Output Protocol and the Device Path
+  Status = gBS->InstallMultipleProtocolInterfaces(
+            &Instance->Handle,
+            &gEfiGraphicsOutputProtocolGuid, &Instance->Gop,
+            &gEfiDevicePathProtocolGuid,     &Instance->DevicePath,
+            NULL
+            );
+
+  if (EFI_ERROR(Status)) {
+    DEBUG((DEBUG_ERROR, "GraphicsOutputDxeInitialize: Can not install the protocol. Exit Status=%r\n", Status));
+    goto EXIT;
+  }
+
+  // Register for an ExitBootServicesEvent
+  // When ExitBootServices starts, this function here will make sure that the graphics driver will shut down properly,
+  // i.e. it will free up all allocated memory and perform any necessary hardware re-configuration.
+  Status = gBS->CreateEvent (
+            EVT_SIGNAL_EXIT_BOOT_SERVICES,
+            TPL_NOTIFY,
+            LcdGraphicsExitBootServicesEvent, NULL,
+            &Instance->ExitBootServicesEvent
+            );
+
+  if (EFI_ERROR(Status)) {
+    DEBUG((DEBUG_ERROR, "GraphicsOutputDxeInitialize: Can not install the ExitBootServicesEvent handler. Exit Status=%r\n", Status));
+    goto EXIT_ERROR_UNINSTALL_PROTOCOL;
+  }
+
+  // To get here, everything must be fine, so just exit
+  goto EXIT;
+
+EXIT_ERROR_UNINSTALL_PROTOCOL:
+  /* The following function could return an error message,
+   * however, to get here something must have gone wrong already,
+   * so preserve the original error, i.e. don't change
+   * the Status variable, even it fails to uninstall the protocol.
+   */
+  gBS->UninstallMultipleProtocolInterfaces (
+    Instance->Handle,
+    &gEfiGraphicsOutputProtocolGuid, &Instance->Gop, // Uninstall Graphics Output protocol
+    &gEfiDevicePathProtocolGuid,     &Instance->DevicePath,     // Uninstall device path
+    NULL
+    );
+
+EXIT:
+  return Status;
+
+}
+
+/***************************************
+ * This function should be called
+ * on Event: ExitBootServices
+ * to free up memory, stop the driver
+ * and uninstall the protocols
+ ***************************************/
+VOID
+LcdGraphicsExitBootServicesEvent (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  // By default, this PCD is FALSE. But if a platform starts a predefined OS that
+  // does not use a framebuffer then we might want to disable the display controller
+  // to avoid to display corrupted information on the screen.
+  if (FeaturePcdGet (PcdGopDisableOnExitBootServices)) {
+    // Turn-off the Display controller
+    LcdShutdown ();
+  }
+}
+
+/***************************************
+ * GraphicsOutput Protocol function, mapping to
+ * EFI_GRAPHICS_OUTPUT_PROTOCOL.QueryMode
+ ***************************************/
+EFI_STATUS
+EFIAPI
+LcdGraphicsQueryMode (
+  IN EFI_GRAPHICS_OUTPUT_PROTOCOL            *This,
+  IN UINT32                                  ModeNumber,
+  OUT UINTN                                  *SizeOfInfo,
+  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION   **Info
+  )
+{
+  EFI_STATUS Status = EFI_SUCCESS;
+  LCD_INSTANCE *Instance;
+
+  Instance = LCD_INSTANCE_FROM_GOP_THIS(This);
+
+  // Setup the hardware if not already done
+  if( !mDisplayInitialized ) {
+    Status = InitializeDisplay(Instance);
+    if (EFI_ERROR(Status)) {
+      goto EXIT;
+    }
+  }
+
+  // Error checking
+  if ( (This == NULL) || (Info == NULL) || (SizeOfInfo == NULL) || (ModeNumber >= This->Mode->MaxMode) ) {
+    DEBUG((DEBUG_ERROR, "LcdGraphicsQueryMode: ERROR - For mode number %d : Invalid Parameter.\n", ModeNumber ));
+    Status = EFI_INVALID_PARAMETER;
+    goto EXIT;
+  }
+
+  *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
+  if (*Info == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto EXIT;
+  }
+
+  *SizeOfInfo = sizeof( EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+
+  Status = LcdPlatformQueryMode (ModeNumber,*Info);
+  if (EFI_ERROR(Status)) {
+    FreePool(*Info);
+  }
+
+EXIT:
+  return Status;
+}
+
+/***************************************
+ * GraphicsOutput Protocol function, mapping to
+ * EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode
+ ***************************************/
+EFI_STATUS
+EFIAPI
+LcdGraphicsSetMode (
+  IN EFI_GRAPHICS_OUTPUT_PROTOCOL   *This,
+  IN UINT32                         ModeNumber
+  )
+{
+  EFI_STATUS                      Status = EFI_SUCCESS;
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL   FillColour;
+  LCD_INSTANCE*                   Instance;
+  LCD_BPP                         Bpp;
+
+  Instance = LCD_INSTANCE_FROM_GOP_THIS (This);
+
+  // Setup the hardware if not already done
+  if(!mDisplayInitialized) {
+    Status = InitializeDisplay (Instance);
+    if (EFI_ERROR(Status)) {
+      goto EXIT;
+    }
+  }
+
+  // Check if this mode is supported
+  if( ModeNumber >= This->Mode->MaxMode ) {
+    DEBUG((DEBUG_ERROR, "LcdGraphicsSetMode: ERROR - Unsupported mode number %d .\n", ModeNumber ));
+    Status = EFI_UNSUPPORTED;
+    goto EXIT;
+  }
+
+  // Set the oscillator frequency to support the new mode
+  Status = LcdPlatformSetMode (ModeNumber);
+  if (EFI_ERROR(Status)) {
+    Status = EFI_DEVICE_ERROR;
+    goto EXIT;
+  }
+
+  // Update the UEFI mode information
+  This->Mode->Mode = ModeNumber;
+  LcdPlatformQueryMode (ModeNumber,&Instance->ModeInfo);
+  Status = LcdPlatformGetBpp(ModeNumber, &Bpp);
+  if (EFI_ERROR(Status)) {
+    DEBUG ((DEBUG_ERROR, "LcdGraphicsSetMode: ERROR - Couldn't get bytes per pixel, status: %r\n", Status));
+    goto EXIT;
+  }
+  This->Mode->FrameBufferSize =  Instance->ModeInfo.VerticalResolution
+                               * Instance->ModeInfo.PixelsPerScanLine
+                               * GetBytesPerPixel(Bpp);
+
+  // Set the hardware to the new mode
+  Status = LcdSetMode (ModeNumber);
+  if (EFI_ERROR(Status)) {
+    Status = EFI_DEVICE_ERROR;
+    goto EXIT;
+  }
+
+  // The UEFI spec requires that we now clear the visible portions of the output display to black.
+
+  // Set the fill colour to black
+  SetMem (&FillColour, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
+
+  // Fill the entire visible area with the same colour.
+  Status = This->Blt (
+      This,
+      &FillColour,
+      EfiBltVideoFill,
+      0,
+      0,
+      0,
+      0,
+      This->Mode->Info->HorizontalResolution,
+      This->Mode->Info->VerticalResolution,
+      0);
+
+EXIT:
+  return Status;
+}
+
+UINTN
+GetBytesPerPixel (
+  IN  LCD_BPP       Bpp
+  )
+{
+  switch(Bpp) {
+  case LCD_BITS_PER_PIXEL_24:
+    return 4;
+
+  case LCD_BITS_PER_PIXEL_16_565:
+  case LCD_BITS_PER_PIXEL_16_555:
+  case LCD_BITS_PER_PIXEL_12_444:
+    return 2;
+
+  case LCD_BITS_PER_PIXEL_8:
+  case LCD_BITS_PER_PIXEL_4:
+  case LCD_BITS_PER_PIXEL_2:
+  case LCD_BITS_PER_PIXEL_1:
+    return 1;
+
+  default:
+    return 0;
+  }
+}
diff --git a/Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.h b/Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.h
new file mode 100644
index 000000000000..8856b79901b6
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.h
@@ -0,0 +1,128 @@ 
+/** @file
+
+  Copyright (c) 2011, 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.
+
+**/
+
+#ifndef __ARM_VE_GRAPHICS_DXE_H__
+#define __ARM_VE_GRAPHICS_DXE_H__
+
+
+#include <Base.h>
+
+#include <Library/DebugLib.h>
+#include <Library/LcdPlatformLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiLib.h>
+
+#include <Protocol/DevicePath.h>
+
+
+//
+// Device structures
+//
+typedef struct {
+  VENDOR_DEVICE_PATH            Guid;
+  EFI_DEVICE_PATH_PROTOCOL      End;
+} LCD_GRAPHICS_DEVICE_PATH;
+
+typedef struct {
+  UINT32                                Signature;
+  EFI_HANDLE                            Handle;
+  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  ModeInfo;
+  EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE     Mode;
+  EFI_GRAPHICS_OUTPUT_PROTOCOL          Gop;
+  LCD_GRAPHICS_DEVICE_PATH              DevicePath;
+  EFI_EVENT                             ExitBootServicesEvent;
+} LCD_INSTANCE;
+
+#define LCD_INSTANCE_SIGNATURE  SIGNATURE_32('l', 'c', 'd', '0')
+
+#define LCD_INSTANCE_FROM_GOP_THIS(a)     CR (a, LCD_INSTANCE, Gop, LCD_INSTANCE_SIGNATURE)
+
+//
+// Function Prototypes
+//
+
+VOID
+LcdGraphicsExitBootServicesEvent (
+    IN EFI_EVENT  Event,
+    IN VOID       *Context
+);
+
+EFI_STATUS
+EFIAPI
+LcdGraphicsQueryMode (
+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
+  IN  UINT32                                ModeNumber,
+  OUT UINTN                                 *SizeOfInfo,
+  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  **Info
+);
+
+EFI_STATUS
+EFIAPI
+LcdGraphicsSetMode (
+  IN EFI_GRAPHICS_OUTPUT_PROTOCOL  *This,
+  IN UINT32                        ModeNumber
+);
+
+EFI_STATUS
+EFIAPI
+LcdGraphicsBlt (
+  IN EFI_GRAPHICS_OUTPUT_PROTOCOL       *This,
+  IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL  *BltBuffer,     OPTIONAL
+  IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION  BltOperation,
+  IN UINTN                              SourceX,
+  IN UINTN                              SourceY,
+  IN UINTN                              DestinationX,
+  IN UINTN                              DestinationY,
+  IN UINTN                              Width,
+  IN UINTN                              Height,
+  IN UINTN                              Delta           OPTIONAL
+);
+
+UINTN
+GetBytesPerPixel (
+  IN  LCD_BPP       Bpp
+  );
+
+EFI_STATUS
+EFIAPI
+GraphicsOutputDxeInitialize (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+);
+
+EFI_STATUS
+InitializeDisplay (
+  IN LCD_INSTANCE* Instance
+);
+
+EFI_STATUS
+LcdIdentify (
+  VOID
+);
+
+EFI_STATUS
+LcdInitialize (
+  EFI_PHYSICAL_ADDRESS  VramBaseAddress
+);
+
+EFI_STATUS
+LcdSetMode (
+  IN UINT32  ModeNumber
+);
+
+VOID
+LcdShutdown (
+  VOID
+);
+
+#endif /* __ARM_VE_GRAPHICS_DXE_H__ */
diff --git a/Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/PL111Lcd.c b/Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/PL111Lcd.c
new file mode 100644
index 000000000000..b5e113b844d4
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/PL111Lcd.c
@@ -0,0 +1,126 @@ 
+/** @file  PL111Lcd.c
+
+  Copyright (c) 2011-2012, 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 <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <Drivers/PL111Lcd.h>
+
+#include "LcdGraphicsOutputDxe.h"
+
+/**********************************************************************
+ *
+ *  This file contains all the bits of the PL111 that are
+ *  platform independent.
+ *
+ **********************************************************************/
+
+EFI_STATUS
+LcdIdentify (
+  VOID
+  )
+{
+  DEBUG ((EFI_D_WARN, "Probing ID registers at 0x%lx for a PL111\n",
+    PL111_REG_CLCD_PERIPH_ID_0));
+
+  // Check if this is a PL111
+  if (MmioRead8 (PL111_REG_CLCD_PERIPH_ID_0) == PL111_CLCD_PERIPH_ID_0 &&
+      MmioRead8 (PL111_REG_CLCD_PERIPH_ID_1) == PL111_CLCD_PERIPH_ID_1 &&
+     (MmioRead8 (PL111_REG_CLCD_PERIPH_ID_2) & 0xf) == PL111_CLCD_PERIPH_ID_2 &&
+      MmioRead8 (PL111_REG_CLCD_PERIPH_ID_3) == PL111_CLCD_PERIPH_ID_3 &&
+      MmioRead8 (PL111_REG_CLCD_P_CELL_ID_0) == PL111_CLCD_P_CELL_ID_0 &&
+      MmioRead8 (PL111_REG_CLCD_P_CELL_ID_1) == PL111_CLCD_P_CELL_ID_1 &&
+      MmioRead8 (PL111_REG_CLCD_P_CELL_ID_2) == PL111_CLCD_P_CELL_ID_2 &&
+      MmioRead8 (PL111_REG_CLCD_P_CELL_ID_3) == PL111_CLCD_P_CELL_ID_3) {
+    return EFI_SUCCESS;
+  }
+  return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+LcdInitialize (
+  IN EFI_PHYSICAL_ADDRESS   VramBaseAddress
+  )
+{
+  // Define start of the VRAM. This never changes for any graphics mode
+  MmioWrite32(PL111_REG_LCD_UP_BASE, (UINT32) VramBaseAddress);
+  MmioWrite32(PL111_REG_LCD_LP_BASE, 0); // We are not using a double buffer
+
+  // Disable all interrupts from the PL111
+  MmioWrite32(PL111_REG_LCD_IMSC, 0);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+LcdSetMode (
+  IN UINT32  ModeNumber
+  )
+{
+  EFI_STATUS        Status;
+  UINT32            HRes;
+  UINT32            HSync;
+  UINT32            HBackPorch;
+  UINT32            HFrontPorch;
+  UINT32            VRes;
+  UINT32            VSync;
+  UINT32            VBackPorch;
+  UINT32            VFrontPorch;
+  UINT32            LcdControl;
+  LCD_BPP           LcdBpp;
+
+  // Set the video mode timings and other relevant information
+  Status = LcdPlatformGetTimings (ModeNumber,
+                                  &HRes,&HSync,&HBackPorch,&HFrontPorch,
+                                  &VRes,&VSync,&VBackPorch,&VFrontPorch);
+  ASSERT_EFI_ERROR (Status);
+  if (EFI_ERROR( Status )) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  Status = LcdPlatformGetBpp (ModeNumber,&LcdBpp);
+  ASSERT_EFI_ERROR (Status);
+  if (EFI_ERROR( Status )) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  // Disable the CLCD_LcdEn bit
+  LcdControl = MmioRead32( PL111_REG_LCD_CONTROL);
+  MmioWrite32(PL111_REG_LCD_CONTROL,  LcdControl & ~1);
+
+  // Set Timings
+  MmioWrite32 (PL111_REG_LCD_TIMING_0, HOR_AXIS_PANEL(HBackPorch, HFrontPorch, HSync, HRes));
+  MmioWrite32 (PL111_REG_LCD_TIMING_1, VER_AXIS_PANEL(VBackPorch, VFrontPorch, VSync, VRes));
+  MmioWrite32 (PL111_REG_LCD_TIMING_2, CLK_SIG_POLARITY(HRes));
+  MmioWrite32 (PL111_REG_LCD_TIMING_3, 0);
+
+  // PL111_REG_LCD_CONTROL
+  LcdControl = PL111_CTRL_LCD_EN | PL111_CTRL_LCD_BPP(LcdBpp) | PL111_CTRL_LCD_TFT | PL111_CTRL_BGR;
+  MmioWrite32(PL111_REG_LCD_CONTROL,  LcdControl);
+
+  // Turn on power to the LCD Panel
+  LcdControl |= PL111_CTRL_LCD_PWR;
+  MmioWrite32(PL111_REG_LCD_CONTROL,  LcdControl);
+
+  return EFI_SUCCESS;
+}
+
+VOID
+LcdShutdown (
+  VOID
+  )
+{
+  // Disable the controller
+  MmioAnd32 (PL111_REG_LCD_CONTROL, ~PL111_CTRL_LCD_EN);
+}
diff --git a/Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/PL111LcdGraphicsOutputDxe.inf b/Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/PL111LcdGraphicsOutputDxe.inf
new file mode 100644
index 000000000000..003cc2ffa912
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Drivers/LcdGraphicsOutputDxe/PL111LcdGraphicsOutputDxe.inf
@@ -0,0 +1,59 @@ 
+#/** @file
+#
+#  Component description file for PL111LcdGraphicsOutputDxe module
+#
+#  Copyright (c) 2011-2012, 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                      = PL111LcdGraphicsDxe
+  FILE_GUID                      = 407B4008-BF5B-11DF-9547-CF16E0D72085
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = LcdGraphicsOutputDxeInitialize
+
+[Sources.common]
+  LcdGraphicsOutputDxe.c
+  LcdGraphicsOutputBlt.c
+  PL111Lcd.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmVExpressPkg/ArmVExpressPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+  ArmLib
+  UefiLib
+  BaseLib
+  DebugLib
+  TimerLib
+  UefiDriverEntryPoint
+  UefiBootServicesTableLib
+  IoLib
+  BaseMemoryLib
+  LcdPlatformLib
+
+[Protocols]
+  gEfiDevicePathProtocolGuid
+  gEfiGraphicsOutputProtocolGuid
+
+[FixedPcd]
+  gArmPlatformTokenSpaceGuid.PcdPL111LcdBase
+
+[FeaturePcd]
+  gArmPlatformTokenSpaceGuid.PcdGopDisableOnExitBootServices
+
+[Depex]
+  gEfiCpuArchProtocolGuid
diff --git a/Platform/ARM/VExpressPkg/Include/Drivers/HdLcd.h b/Platform/ARM/VExpressPkg/Include/Drivers/HdLcd.h
new file mode 100644
index 000000000000..6df97a9dfee6
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Include/Drivers/HdLcd.h
@@ -0,0 +1,89 @@ 
+/** @file  HDLcd.h
+
+ Copyright (c) 2011-2012, 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.
+
+ **/
+
+#ifndef _HDLCD_H_
+#define _HDLCD_H_
+
+//
+// HDLCD Controller Register Offsets
+//
+
+#define HDLCD_REG_VERSION                 ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x000)
+#define HDLCD_REG_INT_RAWSTAT             ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x010)
+#define HDLCD_REG_INT_CLEAR               ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x014)
+#define HDLCD_REG_INT_MASK                ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x018)
+#define HDLCD_REG_INT_STATUS              ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x01C)
+#define HDLCD_REG_FB_BASE                 ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x100)
+#define HDLCD_REG_FB_LINE_LENGTH          ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x104)
+#define HDLCD_REG_FB_LINE_COUNT           ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x108)
+#define HDLCD_REG_FB_LINE_PITCH           ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x10C)
+#define HDLCD_REG_BUS_OPTIONS             ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x110)
+#define HDLCD_REG_V_SYNC                  ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x200)
+#define HDLCD_REG_V_BACK_PORCH            ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x204)
+#define HDLCD_REG_V_DATA                  ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x208)
+#define HDLCD_REG_V_FRONT_PORCH           ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x20C)
+#define HDLCD_REG_H_SYNC                  ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x210)
+#define HDLCD_REG_H_BACK_PORCH            ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x214)
+#define HDLCD_REG_H_DATA                  ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x218)
+#define HDLCD_REG_H_FRONT_PORCH           ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x21C)
+#define HDLCD_REG_POLARITIES              ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x220)
+#define HDLCD_REG_COMMAND                 ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x230)
+#define HDLCD_REG_PIXEL_FORMAT            ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x240)
+#define HDLCD_REG_RED_SELECT              ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x244)
+#define HDLCD_REG_GREEN_SELECT            ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x248)
+#define HDLCD_REG_BLUE_SELECT             ((UINTN)PcdGet32 (PcdArmHdLcdBase) + 0x24C)
+
+
+//
+// HDLCD Values of registers
+//
+
+// HDLCD Interrupt mask, clear and status register
+#define HDLCD_DMA_END                     BIT0    /* DMA has finished reading a frame */
+#define HDLCD_BUS_ERROR                   BIT1    /* DMA bus error */
+#define HDLCD_SYNC                        BIT2    /* Vertical sync */
+#define HDLCD_UNDERRUN                    BIT3    /* No Data available while DATAEN active */
+
+// CLCD_CONTROL Control register
+#define HDLCD_DISABLE                     0
+#define HDLCD_ENABLE                      BIT0
+
+// Bus Options
+#define HDLCD_BURST_1                     BIT0
+#define HDLCD_BURST_2                     BIT1
+#define HDLCD_BURST_4                     BIT2
+#define HDLCD_BURST_8                     BIT3
+#define HDLCD_BURST_16                    BIT4
+
+// Polarities - HIGH
+#define HDLCD_VSYNC_HIGH                  BIT0
+#define HDLCD_HSYNC_HIGH                  BIT1
+#define HDLCD_DATEN_HIGH                  BIT2
+#define HDLCD_DATA_HIGH                   BIT3
+#define HDLCD_PXCLK_HIGH                  BIT4
+// Polarities - LOW (for completion and for ease of understanding the hardware settings)
+#define HDLCD_VSYNC_LOW                   0
+#define HDLCD_HSYNC_LOW                   0
+#define HDLCD_DATEN_LOW                   0
+#define HDLCD_DATA_LOW                    0
+#define HDLCD_PXCLK_LOW                   0
+
+// Pixel Format
+#define HDLCD_LITTLE_ENDIAN              (0 << 31)
+#define HDLCD_BIG_ENDIAN                 (1 << 31)
+
+// Number of bytes per pixel
+#define HDLCD_4BYTES_PER_PIXEL           ((4 - 1) << 3)
+
+#endif /* _HDLCD_H_ */
diff --git a/Platform/ARM/VExpressPkg/Include/Drivers/PL111Lcd.h b/Platform/ARM/VExpressPkg/Include/Drivers/PL111Lcd.h
new file mode 100644
index 000000000000..18e28af805f6
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Include/Drivers/PL111Lcd.h
@@ -0,0 +1,149 @@ 
+/** @file  PL111Lcd.h
+
+ Copyright (c) 2011, 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.
+
+ **/
+
+#ifndef _PL111LCD_H__
+#define _PL111LCD_H__
+
+/**********************************************************************
+ *
+ *  This header file contains all the bits of the PL111 that are
+ *  platform independent.
+ *
+ **********************************************************************/
+
+// Controller Register Offsets
+#define PL111_REG_LCD_TIMING_0            ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x000)
+#define PL111_REG_LCD_TIMING_1            ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x004)
+#define PL111_REG_LCD_TIMING_2            ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x008)
+#define PL111_REG_LCD_TIMING_3            ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x00C)
+#define PL111_REG_LCD_UP_BASE             ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x010)
+#define PL111_REG_LCD_LP_BASE             ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x014)
+#define PL111_REG_LCD_CONTROL             ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x018)
+#define PL111_REG_LCD_IMSC                ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x01C)
+#define PL111_REG_LCD_RIS                 ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x020)
+#define PL111_REG_LCD_MIS                 ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x024)
+#define PL111_REG_LCD_ICR                 ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x028)
+#define PL111_REG_LCD_UP_CURR             ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x02C)
+#define PL111_REG_LCD_LP_CURR             ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x030)
+#define PL111_REG_LCD_PALETTE             ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0x200)
+
+// Identification Register Offsets
+#define PL111_REG_CLCD_PERIPH_ID_0        ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0xFE0)
+#define PL111_REG_CLCD_PERIPH_ID_1        ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0xFE4)
+#define PL111_REG_CLCD_PERIPH_ID_2        ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0xFE8)
+#define PL111_REG_CLCD_PERIPH_ID_3        ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0xFEC)
+#define PL111_REG_CLCD_P_CELL_ID_0        ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0xFF0)
+#define PL111_REG_CLCD_P_CELL_ID_1        ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0xFF4)
+#define PL111_REG_CLCD_P_CELL_ID_2        ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0xFF8)
+#define PL111_REG_CLCD_P_CELL_ID_3        ((UINTN)PcdGet32 (PcdPL111LcdBase) + 0xFFC)
+
+#define PL111_CLCD_PERIPH_ID_0            0x11
+#define PL111_CLCD_PERIPH_ID_1            0x11
+#define PL111_CLCD_PERIPH_ID_2            0x04
+#define PL111_CLCD_PERIPH_ID_3            0x00
+#define PL111_CLCD_P_CELL_ID_0            0x0D
+#define PL111_CLCD_P_CELL_ID_1            0xF0
+#define PL111_CLCD_P_CELL_ID_2            0x05
+#define PL111_CLCD_P_CELL_ID_3            0xB1
+
+/**********************************************************************/
+
+// Register components (register bits)
+
+// This should make life easier to program specific settings in the different registers
+// by simplifying the setting up of the individual bits of each register
+// and then assembling the final register value.
+
+/**********************************************************************/
+
+// Register: PL111_REG_LCD_TIMING_0
+#define HOR_AXIS_PANEL(hbp,hfp,hsw,hor_res) (UINT32)(((UINT32)(hbp) << 24) | ((UINT32)(hfp) << 16) | ((UINT32)(hsw) << 8) | (((UINT32)((hor_res)/16)-1) << 2))
+
+// Register: PL111_REG_LCD_TIMING_1
+#define VER_AXIS_PANEL(vbp,vfp,vsw,ver_res) (UINT32)(((UINT32)(vbp) << 24) | ((UINT32)(vfp) << 16) | ((UINT32)(vsw) << 10) | ((ver_res)-1))
+
+// Register: PL111_REG_LCD_TIMING_2
+#define PL111_BIT_SHIFT_PCD_HI            27
+#define PL111_BIT_SHIFT_BCD               26
+#define PL111_BIT_SHIFT_CPL               16
+#define PL111_BIT_SHIFT_IOE               14
+#define PL111_BIT_SHIFT_IPC               13
+#define PL111_BIT_SHIFT_IHS               12
+#define PL111_BIT_SHIFT_IVS               11
+#define PL111_BIT_SHIFT_ACB               6
+#define PL111_BIT_SHIFT_CLKSEL            5
+#define PL111_BIT_SHIFT_PCD_LO            0
+
+#define PL111_BCD                         (1 << 26)
+#define PL111_IPC                         (1 << 13)
+#define PL111_IHS                         (1 << 12)
+#define PL111_IVS                         (1 << 11)
+
+#define CLK_SIG_POLARITY(hor_res)         (UINT32)(PL111_BCD | PL111_IPC | PL111_IHS | PL111_IVS | (((hor_res)-1) << 16))
+
+// Register: PL111_REG_LCD_TIMING_3
+#define PL111_BIT_SHIFT_LEE               16
+#define PL111_BIT_SHIFT_LED               0
+
+#define PL111_CTRL_WATERMARK              (1 << 16)
+#define PL111_CTRL_LCD_V_COMP             (1 << 12)
+#define PL111_CTRL_LCD_PWR                (1 << 11)
+#define PL111_CTRL_BEPO                   (1 << 10)
+#define PL111_CTRL_BEBO                   (1 << 9)
+#define PL111_CTRL_BGR                    (1 << 8)
+#define PL111_CTRL_LCD_DUAL               (1 << 7)
+#define PL111_CTRL_LCD_MONO_8             (1 << 6)
+#define PL111_CTRL_LCD_TFT                (1 << 5)
+#define PL111_CTRL_LCD_BW                 (1 << 4)
+#define PL111_CTRL_LCD_1BPP               (0 << 1)
+#define PL111_CTRL_LCD_2BPP               (1 << 1)
+#define PL111_CTRL_LCD_4BPP               (2 << 1)
+#define PL111_CTRL_LCD_8BPP               (3 << 1)
+#define PL111_CTRL_LCD_16BPP              (4 << 1)
+#define PL111_CTRL_LCD_24BPP              (5 << 1)
+#define PL111_CTRL_LCD_16BPP_565          (6 << 1)
+#define PL111_CTRL_LCD_12BPP_444          (7 << 1)
+#define PL111_CTRL_LCD_BPP(Bpp)           ((Bpp) << 1)
+#define PL111_CTRL_LCD_EN                 1
+
+/**********************************************************************/
+
+// Register: PL111_REG_LCD_TIMING_0
+#define PL111_LCD_TIMING_0_HBP(hbp)       (((hbp) & 0xFF) << 24)
+#define PL111_LCD_TIMING_0_HFP(hfp)       (((hfp) & 0xFF) << 16)
+#define PL111_LCD_TIMING_0_HSW(hsw)       (((hsw) & 0xFF) << 8)
+#define PL111_LCD_TIMING_0_PPL(ppl)       (((hsw) & 0x3F) << 2)
+
+// Register: PL111_REG_LCD_TIMING_1
+#define PL111_LCD_TIMING_1_VBP(vbp)       (((vbp) & 0xFF) << 24)
+#define PL111_LCD_TIMING_1_VFP(vfp)       (((vfp) & 0xFF) << 16)
+#define PL111_LCD_TIMING_1_VSW(vsw)       (((vsw) & 0x3F) << 10)
+#define PL111_LCD_TIMING_1_LPP(lpp)        ((lpp) & 0xFC)
+
+// Register: PL111_REG_LCD_TIMING_2
+#define PL111_BIT_MASK_PCD_HI             0xF8000000
+#define PL111_BIT_MASK_BCD                0x04000000
+#define PL111_BIT_MASK_CPL                0x03FF0000
+#define PL111_BIT_MASK_IOE                0x00004000
+#define PL111_BIT_MASK_IPC                0x00002000
+#define PL111_BIT_MASK_IHS                0x00001000
+#define PL111_BIT_MASK_IVS                0x00000800
+#define PL111_BIT_MASK_ACB                0x000007C0
+#define PL111_BIT_MASK_CLKSEL             0x00000020
+#define PL111_BIT_MASK_PCD_LO             0x0000001F
+
+// Register: PL111_REG_LCD_TIMING_3
+#define PL111_BIT_MASK_LEE                0x00010000
+#define PL111_BIT_MASK_LED                0x0000007F
+
+#endif /* _PL111LCD_H__ */
diff --git a/Platform/ARM/VExpressPkg/Include/Library/ArmPlatformSysConfigLib.h b/Platform/ARM/VExpressPkg/Include/Library/ArmPlatformSysConfigLib.h
new file mode 100644
index 000000000000..39a0cc7f734c
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Include/Library/ArmPlatformSysConfigLib.h
@@ -0,0 +1,63 @@ 
+/** @file  ArmPlatformSysConfigLib.h
+
+  Copyright (c) 2011-2012, 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.
+
+**/
+
+#ifndef __ARM_PLATFORM_SYS_CONFIG_H__
+#define __ARM_PLATFORM_SYS_CONFIG_H__
+
+#include <Base.h>
+
+/* This header file makes it easier to access the System Configuration Registers
+ * in the ARM Versatile Express motherboard.
+ */
+
+//
+// Typedef
+//
+typedef UINT32  SYS_CONFIG_FUNCTION;
+
+//
+// Functions
+//
+RETURN_STATUS
+ArmPlatformSysConfigInitialize (
+  VOID
+  );
+
+RETURN_STATUS
+ArmPlatformSysConfigGet (
+  IN  SYS_CONFIG_FUNCTION   Function,
+  OUT UINT32*               Value
+  );
+
+RETURN_STATUS
+ArmPlatformSysConfigGetValues (
+  IN  SYS_CONFIG_FUNCTION   Function,
+  IN  UINTN                 Size,
+  OUT UINT32*               Values
+  );
+
+RETURN_STATUS
+ArmPlatformSysConfigSet (
+  IN  SYS_CONFIG_FUNCTION   Function,
+  IN  UINT32                Value
+  );
+
+RETURN_STATUS
+ArmPlatformSysConfigSetDevice (
+  IN  SYS_CONFIG_FUNCTION   Function,
+  IN  UINT32                Device,
+  IN  UINT32                Value
+  );
+
+#endif /* __SYS_CFG_REGISTERS_H__ */
diff --git a/Platform/ARM/VExpressPkg/Include/Library/LcdPlatformLib.h b/Platform/ARM/VExpressPkg/Include/Library/LcdPlatformLib.h
new file mode 100644
index 000000000000..b9bdf471e2d6
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Include/Library/LcdPlatformLib.h
@@ -0,0 +1,221 @@ 
+/** @file
+
+ Copyright (c) 2011, 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.
+
+ **/
+
+#ifndef __LCDPLATFORMLIB_H
+#define __LCDPLATFORMLIB_H
+
+#include <Protocol/GraphicsOutput.h>
+
+#define LCD_VRAM_SIZE                     SIZE_8MB
+
+//
+// Modes definitions
+//
+#define VGA                               0
+#define SVGA                              1
+#define XGA                               2
+#define SXGA                              3
+#define WSXGA                             4
+#define UXGA                              5
+#define HD                                6
+
+//
+// VGA Mode: 640 x 480
+//
+#define VGA_H_RES_PIXELS                  640
+#define VGA_V_RES_PIXELS                  480
+#define VGA_OSC_FREQUENCY                 23750000  /* 0x016A6570 */
+
+#define VGA_H_SYNC                        ( 80 - 1)
+#define VGA_H_FRONT_PORCH                 ( 16 - 1)
+#define VGA_H_BACK_PORCH                  ( 64 - 1)
+
+#define VGA_V_SYNC                        (  4 - 1)
+#define VGA_V_FRONT_PORCH                 (  3 - 1)
+#define VGA_V_BACK_PORCH                  ( 13 - 1)
+
+//
+// SVGA Mode: 800 x 600
+//
+#define SVGA_H_RES_PIXELS                 800
+#define SVGA_V_RES_PIXELS                 600
+#define SVGA_OSC_FREQUENCY                38250000  /* 0x0247A610 */
+
+#define SVGA_H_SYNC                       ( 80 - 1)
+#define SVGA_H_FRONT_PORCH                ( 32 - 1)
+#define SVGA_H_BACK_PORCH                 (112 - 1)
+
+#define SVGA_V_SYNC                       (  4 - 1)
+#define SVGA_V_FRONT_PORCH                (  3 - 1)
+#define SVGA_V_BACK_PORCH                 ( 17 - 1)
+
+//
+// XGA Mode: 1024 x 768
+//
+#define XGA_H_RES_PIXELS                  1024
+#define XGA_V_RES_PIXELS                  768
+#define XGA_OSC_FREQUENCY                 63500000  /* 0x03C8EEE0 */
+
+#define XGA_H_SYNC                        (104 - 1)
+#define XGA_H_FRONT_PORCH                 ( 48 - 1)
+#define XGA_H_BACK_PORCH                  (152 - 1)
+
+#define XGA_V_SYNC                        (  4 - 1)
+#define XGA_V_FRONT_PORCH                 (  3 - 1)
+#define XGA_V_BACK_PORCH                  ( 23 - 1)
+
+//
+// SXGA Mode: 1280 x 1024
+//
+#define SXGA_H_RES_PIXELS                 1280
+#define SXGA_V_RES_PIXELS                 1024
+#define SXGA_OSC_FREQUENCY                109000000  /* 0x067F3540 */
+
+#define SXGA_H_SYNC                       (136 - 1)
+#define SXGA_H_FRONT_PORCH                ( 80 - 1)
+#define SXGA_H_BACK_PORCH                 (216 - 1)
+
+#define SXGA_V_SYNC                       (  7 - 1)
+#define SXGA_V_FRONT_PORCH                (  3 - 1)
+#define SXGA_V_BACK_PORCH                 ( 29 - 1)
+
+//
+// WSXGA+ Mode: 1680 x 1050
+//
+#define WSXGA_H_RES_PIXELS                1680
+#define WSXGA_V_RES_PIXELS                1050
+#define WSXGA_OSC_FREQUENCY               147000000  /* 0x08C30AC0 */
+
+#define WSXGA_H_SYNC                      (170 - 1)
+#define WSXGA_H_FRONT_PORCH               (104 - 1)
+#define WSXGA_H_BACK_PORCH                (274 - 1)
+
+#define WSXGA_V_SYNC                      (  5 - 1)
+#define WSXGA_V_FRONT_PORCH               (  4 - 1)
+#define WSXGA_V_BACK_PORCH                ( 41 - 1)
+
+//
+// UXGA Mode: 1600 x 1200
+//
+#define UXGA_H_RES_PIXELS                 1600
+#define UXGA_V_RES_PIXELS                 1200
+#define UXGA_OSC_FREQUENCY                161000000  /* 0x0998AA40 */
+
+#define UXGA_H_SYNC                       (168 - 1)
+#define UXGA_H_FRONT_PORCH                (112 - 1)
+#define UXGA_H_BACK_PORCH                 (280 - 1)
+
+#define UXGA_V_SYNC                       (  4 - 1)
+#define UXGA_V_FRONT_PORCH                (  3 - 1)
+#define UXGA_V_BACK_PORCH                 ( 38 - 1)
+
+//
+// HD Mode: 1920 x 1080
+//
+#define HD_H_RES_PIXELS                   1920
+#define HD_V_RES_PIXELS                   1080
+#define HD_OSC_FREQUENCY                  165000000  /* 0x09D5B340 */
+
+#define HD_H_SYNC                         ( 79 - 1)
+#define HD_H_FRONT_PORCH                  (128 - 1)
+#define HD_H_BACK_PORCH                   (328 - 1)
+
+#define HD_V_SYNC                         (  5 - 1)
+#define HD_V_FRONT_PORCH                  (  3 - 1)
+#define HD_V_BACK_PORCH                   ( 32 - 1)
+
+//
+// Colour Masks
+//
+
+#define LCD_24BPP_RED_MASK              0x00FF0000
+#define LCD_24BPP_GREEN_MASK            0x0000FF00
+#define LCD_24BPP_BLUE_MASK             0x000000FF
+#define LCD_24BPP_RESERVED_MASK         0xFF000000
+
+#define LCD_16BPP_555_RED_MASK          0x00007C00
+#define LCD_16BPP_555_GREEN_MASK        0x000003E0
+#define LCD_16BPP_555_BLUE_MASK         0x0000001F
+#define LCD_16BPP_555_RESERVED_MASK     0x00000000
+
+#define LCD_16BPP_565_RED_MASK          0x0000F800
+#define LCD_16BPP_565_GREEN_MASK        0x000007E0
+#define LCD_16BPP_565_BLUE_MASK         0x0000001F
+#define LCD_16BPP_565_RESERVED_MASK     0x00008000
+
+#define LCD_12BPP_444_RED_MASK          0x00000F00
+#define LCD_12BPP_444_GREEN_MASK        0x000000F0
+#define LCD_12BPP_444_BLUE_MASK         0x0000000F
+#define LCD_12BPP_444_RESERVED_MASK     0x0000F000
+
+
+// The enumeration indexes maps the PL111 LcdBpp values used in the LCD Control Register
+typedef enum {
+  LCD_BITS_PER_PIXEL_1 = 0,
+  LCD_BITS_PER_PIXEL_2,
+  LCD_BITS_PER_PIXEL_4,
+  LCD_BITS_PER_PIXEL_8,
+  LCD_BITS_PER_PIXEL_16_555,
+  LCD_BITS_PER_PIXEL_24,
+  LCD_BITS_PER_PIXEL_16_565,
+  LCD_BITS_PER_PIXEL_12_444
+} LCD_BPP;
+
+
+EFI_STATUS
+LcdPlatformInitializeDisplay (
+  IN EFI_HANDLE   Handle
+  );
+
+EFI_STATUS
+LcdPlatformGetVram (
+  OUT EFI_PHYSICAL_ADDRESS*                 VramBaseAddress,
+  OUT UINTN*                                VramSize
+  );
+
+UINT32
+LcdPlatformGetMaxMode (
+  VOID
+  );
+
+EFI_STATUS
+LcdPlatformSetMode (
+  IN UINT32                                 ModeNumber
+  );
+
+EFI_STATUS
+LcdPlatformQueryMode (
+  IN  UINT32                                ModeNumber,
+  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info
+  );
+
+EFI_STATUS
+LcdPlatformGetTimings (
+  IN  UINT32                              ModeNumber,
+  OUT UINT32*                             HRes,
+  OUT UINT32*                             HSync,
+  OUT UINT32*                             HBackPorch,
+  OUT UINT32*                             HFrontPorch,
+  OUT UINT32*                             VRes,
+  OUT UINT32*                             VSync,
+  OUT UINT32*                             VBackPorch,
+  OUT UINT32*                             VFrontPorch
+  );
+
+EFI_STATUS
+LcdPlatformGetBpp (
+  IN  UINT32                                ModeNumber,
+  OUT LCD_BPP*                              Bpp
+  );
+
+#endif
diff --git a/Platform/ARM/VExpressPkg/Include/Platform/CTA15-A7/ArmPlatform.h b/Platform/ARM/VExpressPkg/Include/Platform/CTA15-A7/ArmPlatform.h
new file mode 100644
index 000000000000..b52f89a5cbf8
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Include/Platform/CTA15-A7/ArmPlatform.h
@@ -0,0 +1,154 @@ 
+/** @file
+*  Header defining Versatile Express constants (Base addresses, sizes, flags)
+*
+*  Copyright (c) 2012, ARM Limited. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef __ARM_VEXPRESS_CTA15A7_H__
+#define __ARM_VEXPRESS_CTA15A7_H__
+
+#include <VExpressMotherBoard.h>
+
+/***********************************************************************************
+// Platform Memory Map
+************************************************************************************/
+
+// Motherboard Peripheral and On-chip peripheral
+#define ARM_VE_BOARD_PERIPH_BASE              0x1C010000
+
+#ifdef ARM_BIGLITTLE_TC2
+
+// Secure NOR Flash
+#define ARM_VE_SEC_NOR0_BASE                  0x00000000
+#define ARM_VE_SEC_NOR0_SZ                    SIZE_64MB
+
+// Secure RAM
+#define ARM_VE_SEC_RAM0_BASE                  0x04000000
+#define ARM_VE_SEC_RAM0_SZ                    SIZE_64MB
+
+#endif
+
+// NOR Flash 0
+#define ARM_VE_SMB_NOR0_BASE                  0x08000000
+#define ARM_VE_SMB_NOR0_SZ                    SIZE_64MB
+// NOR Flash 1
+#define ARM_VE_SMB_NOR1_BASE                  0x0C000000
+#define ARM_VE_SMB_NOR1_SZ                    SIZE_64MB
+
+// SRAM
+#define ARM_VE_SMB_SRAM_BASE                  0x14000000
+#define ARM_VE_SMB_SRAM_SZ                    SIZE_32MB
+
+// USB, Ethernet, VRAM
+#ifdef ARM_BIGLITTLE_TC2
+#define ARM_VE_SMB_PERIPH_BASE                0x18000000
+#define ARM_VE_SMB_PERIPH_SZ                  (SIZE_64MB + SIZE_32MB + SIZE_16MB)
+#else
+#define ARM_VE_SMB_PERIPH_BASE                0x1C000000
+#define ARM_VE_SMB_PERIPH_SZ                  (SIZE_64MB + SIZE_16MB)
+#endif
+#define PL111_CLCD_VRAM_MOTHERBOARD_BASE      ARM_VE_SMB_PERIPH_BASE
+
+// On-Chip non-secure ROM
+#ifdef ARM_BIGLITTLE_TC2
+#define ARM_VE_TC2_NON_SECURE_ROM_BASE        0x1F000000
+#define ARM_VE_TC2_NON_SECURE_ROM_SZ          SIZE_16MB
+#endif
+
+// On-Chip Peripherals
+#define ARM_VE_ONCHIP_PERIPH_BASE             0x20000000
+#define ARM_VE_ONCHIP_PERIPH_SZ               0x10000000
+
+// On-Chip non-secure SRAM
+#ifdef ARM_BIGLITTLE_TC2
+#define ARM_VE_TC2_NON_SECURE_SRAM_BASE       0x2E000000
+#define ARM_VE_TC2_NON_SECURE_SRAM_SZ         SIZE_64KB
+#endif
+
+// Allocate a section for the VRAM (Video RAM)
+// If 0 then allow random memory allocation
+#define LCD_VRAM_CORE_TILE_BASE               0
+
+// Define SEC phase sync point
+#define ARM_SEC_EVENT_BOOT_IMAGE_TABLE_IS_AVAILABLE   (ARM_SEC_EVENT_MAX + 1)
+
+/***********************************************************************************
+   Core Tile memory-mapped Peripherals
+************************************************************************************/
+
+// PL354 Static Memory Controller Base
+#ifdef ARM_BIGLITTLE_TC2
+#define ARM_VE_SMC_CTRL_BASE                    0x7FFD0000
+#else
+#define ARM_VE_SMC_CTRL_BASE                    (ARM_VE_BOARD_PERIPH_BASE + 0xE1000)
+#endif
+
+#define ARM_CTA15A7_SCC_BASE                    0x7FFF0000
+#define ARM_CTA15A7_SCC_CFGREG48                (ARM_CTA15A7_SCC_BASE + 0x700)
+
+#define ARM_CTA15A7_SCC_SYSINFO                 ARM_CTA15A7_SCC_CFGREG48
+
+#define ARM_CTA15A7_SCC_SYSINFO_CLUSTER_A7_NUM_CPU(val)         (((val) >> 20) & 0xF)
+#define ARM_CTA15A7_SCC_SYSINFO_CLUSTER_A15_NUM_CPU(val)        (((val) >> 16) & 0xF)
+#define ARM_CTA15A7_SCC_SYSINFO_ACTIVE_CLUSTER_A15              (1 << 0)
+#define ARM_CTA15A7_SCC_SYSINFO_ACTIVE_CLUSTER_A7               (1 << 1)
+#define ARM_CTA15A7_SCC_SYSINFO_UEFI_RESTORE_DEFAULT_NORFLASH   (1 << 4)
+
+#define ARM_CTA15A7_SPC_BASE                    0x7FFF0B00
+#define ARM_CTA15A7_SPC_WAKE_INT_MASK           (ARM_CTA15A7_SPC_BASE + 0x24)
+#define ARM_CTA15A7_SPC_STANDBYWFI_STAT         (ARM_CTA15A7_SPC_BASE + 0x3C)
+#define ARM_CTA15A7_SPC_A15_BX_ADDR0            (ARM_CTA15A7_SPC_BASE + 0x68)
+#define ARM_CTA15A7_SPC_A15_BX_ADDR1            (ARM_CTA15A7_SPC_BASE + 0x6C)
+#define ARM_CTA15A7_SPC_A15_BX_ADDR2            (ARM_CTA15A7_SPC_BASE + 0x70)
+#define ARM_CTA15A7_SPC_A15_BX_ADDR3            (ARM_CTA15A7_SPC_BASE + 0x74)
+#define ARM_CTA15A7_SPC_A7_BX_ADDR0             (ARM_CTA15A7_SPC_BASE + 0x78)
+#define ARM_CTA15A7_SPC_A7_BX_ADDR1             (ARM_CTA15A7_SPC_BASE + 0x7C)
+#define ARM_CTA15A7_SPC_A7_BX_ADDR2             (ARM_CTA15A7_SPC_BASE + 0x80)
+#define ARM_CTA15A7_SPC_A7_BX_ADDR3             (ARM_CTA15A7_SPC_BASE + 0x84)
+
+#define ARM_CTA15A7_SPC_WAKE_INT_MASK_IRQ_A15_MASK_0  (1 << 0)
+#define ARM_CTA15A7_SPC_WAKE_INT_MASK_IRQ_A15_MASK_1  (1 << 1)
+#define ARM_CTA15A7_SPC_WAKE_INT_MASK_FIQ_A15_MASK_0  (1 << 2)
+#define ARM_CTA15A7_SPC_WAKE_INT_MASK_FIQ_A15_MASK_1  (1 << 3)
+#define ARM_CTA15A7_SPC_WAKE_INT_MASK_IRQ_A7_MASK_0   (1 << 4)
+#define ARM_CTA15A7_SPC_WAKE_INT_MASK_IRQ_A7_MASK_1   (1 << 5)
+#define ARM_CTA15A7_SPC_WAKE_INT_MASK_IRQ_A7_MASK_2   (1 << 6)
+#define ARM_CTA15A7_SPC_WAKE_INT_MASK_FIQ_A7_MASK_0   (1 << 7)
+#define ARM_CTA15A7_SPC_WAKE_INT_MASK_FIQ_A7_MASK_1   (1 << 8)
+#define ARM_CTA15A7_SPC_WAKE_INT_MASK_FIQ_A7_MASK_2   (1 << 9)
+
+#define ARM_CTA15A7_SPC_STANDBYWFI_STAT_A15_0   (1 << 0)
+#define ARM_CTA15A7_SPC_STANDBYWFI_STAT_A15_1   (1 << 1)
+#define ARM_CTA15A7_SPC_STANDBYWFI_STAT_A15_L2  (1 << 2)
+#define ARM_CTA15A7_SPC_STANDBYWFI_STAT_A7_0    (1 << 3)
+#define ARM_CTA15A7_SPC_STANDBYWFI_STAT_A7_1    (1 << 4)
+#define ARM_CTA15A7_SPC_STANDBYWFI_STAT_A7_2    (1 << 5)
+#define ARM_CTA15A7_SPC_STANDBYWFI_STAT_A7_L2   (1 << 6)
+
+
+/***********************************************************************************
+// Memory-mapped peripherals
+************************************************************************************/
+
+/*// SP810 Controller
+#undef SP810_CTRL_BASE
+#define SP810_CTRL_BASE                         0x1C020000
+
+// PL111 Colour LCD Controller
+#define PL111_CLCD_SITE                         ARM_VE_MOTHERBOARD_SITE
+#define PL111_CLCD_MOTHERBOARD_VIDEO_MODE_OSC_ID  1
+#define PL111_CLCD_CORE_TILE_VIDEO_MODE_OSC_ID  1
+
+// VRAM offset for the PL111 Colour LCD Controller on the motherboard
+#define VRAM_MOTHERBOARD_BASE                     (ARM_VE_SMB_PERIPH_BASE   + 0x00000)*/
+
+#endif
diff --git a/Platform/ARM/VExpressPkg/Include/Platform/RTSM/ArmPlatform.h b/Platform/ARM/VExpressPkg/Include/Platform/RTSM/ArmPlatform.h
new file mode 100644
index 000000000000..d856b6daa1d7
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Include/Platform/RTSM/ArmPlatform.h
@@ -0,0 +1,79 @@ 
+/** @file
+*  Header defining Versatile Express constants (Base addresses, sizes, flags)
+*
+*  Copyright (c) 2011, 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_VEXPRESS_H__
+#define __ARM_VEXPRESS_H__
+
+#include <VExpressMotherBoard.h>
+
+/***********************************************************************************
+// Platform Memory Map
+************************************************************************************/
+
+// Can be NOR0, NOR1, DRAM
+#define ARM_VE_REMAP_BASE                       0x00000000
+#define ARM_VE_REMAP_SZ                         SIZE_64MB
+
+// Motherboard Peripheral and On-chip peripheral
+#define ARM_VE_BOARD_PERIPH_BASE                0x1C010000
+
+// NOR Flash 1
+// There is typo in the reference manual for the Base address of NOR Flash 1
+#define ARM_VE_SMB_NOR0_BASE                    0x08000000
+#define ARM_VE_SMB_NOR0_SZ                      SIZE_64MB
+// NOR Flash 2
+#define ARM_VE_SMB_NOR1_BASE                    0x0C000000
+#define ARM_VE_SMB_NOR1_SZ                      SIZE_64MB
+// SRAM
+#define ARM_VE_SMB_SRAM_BASE                    0x2E000000
+#define ARM_VE_SMB_SRAM_SZ                      SIZE_64KB
+// USB, Ethernet, VRAM
+#define ARM_VE_SMB_PERIPH_BASE                  0x18800000
+#define ARM_VE_SMB_PERIPH_SZ                    (SIZE_64MB - SIZE_8MB)
+
+#define PL111_CLCD_VRAM_MOTHERBOARD_BASE        0x18000000
+#define PL111_CLCD_VRAM_MOTHERBOARD_SIZE        0x800000
+
+// DRAM
+#define ARM_VE_DRAM_BASE                        PcdGet64 (PcdSystemMemoryBase)
+#define ARM_VE_DRAM_SZ                          PcdGet64 (PcdSystemMemorySize)
+
+// This can be any value since we only support motherboard PL111
+#define LCD_VRAM_CORE_TILE_BASE                 0x00000000
+
+// On-chip peripherals (Snoop Control Unit etc...)
+#define ARM_VE_ON_CHIP_PERIPH_BASE              0x2C000000
+// Note: The TRM says not all the peripherals are implemented
+#define ARM_VE_ON_CHIP_PERIPH_SZ                SIZE_256MB
+
+
+// External AXI between daughterboards (Logic Tile)
+#define ARM_VE_EXT_AXI_BASE                     0x2E010000 // Not modelled
+#define ARM_VE_EXT_AXI_SZ                       0x20000000  /* 512 MB */
+
+/***********************************************************************************
+// Memory-mapped peripherals
+************************************************************************************/
+
+// SP810 Controller
+#undef SP810_CTRL_BASE
+#define SP810_CTRL_BASE                         0x1C020000
+
+// PL111 Colour LCD Controller
+#define PL111_CLCD_SITE                         ARM_VE_MOTHERBOARD_SITE
+#define PL111_CLCD_MOTHERBOARD_VIDEO_MODE_OSC_ID  1
+#define PL111_CLCD_CORE_TILE_VIDEO_MODE_OSC_ID  1
+
+#endif
diff --git a/Platform/ARM/VExpressPkg/Include/VExpressMotherBoard.h b/Platform/ARM/VExpressPkg/Include/VExpressMotherBoard.h
new file mode 100644
index 000000000000..38691c35828b
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Include/VExpressMotherBoard.h
@@ -0,0 +1,140 @@ 
+/** @file
+*  Header defining Versatile Express constants (Base addresses, sizes, flags)
+*
+*  Copyright (c) 2011-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 __VEXPRESSMOTHERBOARD_H_
+#define __VEXPRESSMOTHERBOARD_H_
+
+#include <ArmPlatform.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)
+
+// SP810 Controller
+#ifndef SP810_CTRL_BASE
+#define SP810_CTRL_BASE                           (ARM_VE_BOARD_PERIPH_BASE + 0x01000)
+#endif
+
+// PL111 Colour LCD Controller - motherboard
+#define PL111_CLCD_MOTHERBOARD_BASE               (ARM_VE_BOARD_PERIPH_BASE + 0x1F000)
+#define PL111_CLCD_MOTHERBOARD_VIDEO_MODE_OSC_ID  1
+
+// VRAM offset for the PL111 Colour LCD Controller on the motherboard
+#define VRAM_MOTHERBOARD_BASE                     (ARM_VE_SMB_PERIPH_BASE   + 0x00000)
+
+#define ARM_VE_SYS_PROC_ID_HBI                    0xFFF
+#define ARM_VE_SYS_PROC_ID_MASK                   (UINT32)(0xFFU << 24)
+#define ARM_VE_SYS_PROC_ID_UNSUPPORTED            (UINT32)(0xFFU << 24)
+#define ARM_VE_SYS_PROC_ID_CORTEX_A9              (UINT32)(0x0CU << 24)
+#define ARM_VE_SYS_PROC_ID_CORTEX_A5              (UINT32)(0x12U << 24)
+#define ARM_VE_SYS_PROC_ID_CORTEX_A15             (UINT32)(0x14U << 24)
+#define ARM_VE_SYS_PROC_ID_CORTEX_A7              (UINT32)(0x18U << 24)
+#define ARM_VE_SYS_PROC_ID_CORTEX_A12             (UINT32)(0x1CU << 24)
+
+// Boot Master Select:
+// 0 = Site 1 boot master
+// 1 = Site 2 boot master
+#define ARM_VE_SYS_MISC_MASTERSITE                (1 << 14)
+//
+// 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)
+
+//
+// System ID
+//
+// All RTSM VE models have the same System ID : 0x225F500
+//
+// FVP models have a different System ID.
+// Default Base model System ID : 0x00201100
+// [31:28] Rev     - Board revision:          0x0     = Rev A
+// [27:16] HBI     - HBI board number in BCD: 0x020   = v8 Base Platform
+// [15:12] Variant - Build variant of board:  0x1     = Variant B. (GIC 64k map)
+// [11:8]  Plat    - Platform type:           0x1     = Model
+// [7:0]   FPGA    - FPGA build, BCD coded:   0x00
+//
+//HBI = 010 = Foundation Model
+//HBI = 020 = Base Platform
+//
+// And specifically, the GIC register banks start at the following
+// addresses:
+//              Variant = 0             Variant = 1
+//GICD          0x2c001000              0x2f000000
+//GICC          0x2c002000              0x2c000000
+//GICH          0x2c004000              0x2c010000
+//GICV          0x2c006000              0x2c020000
+
+#define ARM_FVP_BASE_BOARD_SYS_ID       (0x00200100)
+#define ARM_FVP_FOUNDATION_BOARD_SYS_ID (0x00100100)
+
+#define ARM_FVP_SYS_ID_REV_MASK        (UINT32)(0xFUL   << 28)
+#define ARM_FVP_SYS_ID_HBI_MASK        (UINT32)(0xFFFUL << 16)
+#define ARM_FVP_SYS_ID_VARIANT_MASK    (UINT32)(0xFUL   << 12)
+#define ARM_FVP_SYS_ID_PLAT_MASK       (UINT32)(0xFUL   << 8 )
+#define ARM_FVP_SYS_ID_FPGA_MASK       (UINT32)(0xFFUL  << 0 )
+#define ARM_FVP_GIC_VE_MMAP            0x0
+#define ARM_FVP_GIC_BASE_MMAP          (UINT32)(1 << 12)
+
+// The default SYS_IDs. These can be changed when starting the model.
+#define ARM_RTSM_SYS_ID                (0x225F500)
+#define ARM_FVP_BASE_SYS_ID            (ARM_FVP_BASE_BOARD_SYS_ID | ARM_FVP_GIC_BASE_MMAP)
+#define ARM_FVP_FOUNDATION_SYS_ID      (ARM_FVP_FOUNDATION_BOARD_SYS_ID | ARM_FVP_GIC_BASE_MMAP)
+
+#endif /* VEXPRESSMOTHERBOARD_H_ */
diff --git a/Platform/ARM/VExpressPkg/Library/ArmVExpressLibCTA15-A7/ArmVExpressLib.inf b/Platform/ARM/VExpressPkg/Library/ArmVExpressLibCTA15-A7/ArmVExpressLib.inf
new file mode 100644
index 000000000000..9e81b1c1cc16
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Library/ArmVExpressLibCTA15-A7/ArmVExpressLib.inf
@@ -0,0 +1,54 @@ 
+#/* @file
+#
+#  Copyright (c) 2011-2012, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#*/
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = CTA15A7ArmVExpressLib
+  FILE_GUID                      = b98a6cb7-d472-4128-ad62-a7347f85ce13
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = ArmPlatformLib
+
+[Packages]
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  ArmPkg/ArmPkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  Platform/ARM/VExpressPkg/ArmVExpressPkg.dec
+
+[LibraryClasses]
+  IoLib
+  ArmLib
+  MemoryAllocationLib
+  SerialPortLib
+
+[Sources.common]
+  CTA15-A7.c
+  CTA15-A7Mem.c
+  CTA15-A7Helper.asm | RVCT
+  CTA15-A7Helper.S   | GCC
+
+[FeaturePcd]
+  gEmbeddedTokenSpaceGuid.PcdCacheEnable
+
+[FixedPcd]
+  gArmPlatformTokenSpaceGuid.PcdCoreCount
+
+  gArmTokenSpaceGuid.PcdSystemMemoryBase
+  gArmTokenSpaceGuid.PcdSystemMemorySize
+  gArmTokenSpaceGuid.PcdFvBaseAddress
+
+[Ppis]
+  gArmMpCoreInfoPpiGuid
diff --git a/Platform/ARM/VExpressPkg/Library/ArmVExpressLibCTA15-A7/CTA15-A7.c b/Platform/ARM/VExpressPkg/Library/ArmVExpressLibCTA15-A7/CTA15-A7.c
new file mode 100644
index 000000000000..93f4d82f1988
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Library/ArmVExpressLibCTA15-A7/CTA15-A7.c
@@ -0,0 +1,195 @@ 
+/** @file
+*
+*  Copyright (c) 2012, ARM Limited. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <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 mVersatileExpressCTA15A7InfoTable[] = {
+  {
+    // Cluster 0, Core 0
+    0x0, 0x0,
+
+    // MP Core MailBox Set/Get/Clear Addresses and Clear Value
+    (EFI_PHYSICAL_ADDRESS)ARM_CTA15A7_SPC_A15_BX_ADDR0,
+    (EFI_PHYSICAL_ADDRESS)ARM_CTA15A7_SPC_A15_BX_ADDR0,
+    (EFI_PHYSICAL_ADDRESS)ARM_CTA15A7_SPC_A15_BX_ADDR0,
+    (UINT64)0
+  },
+  {
+    // Cluster 0, Core 1
+    0x0, 0x1,
+
+    // MP Core MailBox Set/Get/Clear Addresses and Clear Value
+    (EFI_PHYSICAL_ADDRESS)ARM_CTA15A7_SPC_A15_BX_ADDR1,
+    (EFI_PHYSICAL_ADDRESS)ARM_CTA15A7_SPC_A15_BX_ADDR1,
+    (EFI_PHYSICAL_ADDRESS)ARM_CTA15A7_SPC_A15_BX_ADDR1,
+    (UINT64)0
+  },
+#ifndef ARM_BIGLITTLE_TC2
+  {
+    // Cluster 0, Core 2
+    0x0, 0x2,
+
+    // MP Core MailBox Set/Get/Clear Addresses and Clear Value
+    (EFI_PHYSICAL_ADDRESS)ARM_CTA15A7_SPC_A15_BX_ADDR2,
+    (EFI_PHYSICAL_ADDRESS)ARM_CTA15A7_SPC_A15_BX_ADDR2,
+    (EFI_PHYSICAL_ADDRESS)ARM_CTA15A7_SPC_A15_BX_ADDR2,
+    (UINT64)0
+  },
+  {
+    // Cluster 0, Core 3
+    0x0, 0x3,
+
+    // MP Core MailBox Set/Get/Clear Addresses and Clear Value
+    (EFI_PHYSICAL_ADDRESS)ARM_CTA15A7_SPC_A15_BX_ADDR3,
+    (EFI_PHYSICAL_ADDRESS)ARM_CTA15A7_SPC_A15_BX_ADDR3,
+    (EFI_PHYSICAL_ADDRESS)ARM_CTA15A7_SPC_A15_BX_ADDR3,
+    (UINT64)0
+  },
+#endif
+  {
+    // Cluster 1, Core 0
+    0x1, 0x0,
+
+    // MP Core MailBox Set/Get/Clear Addresses and Clear Value
+    (EFI_PHYSICAL_ADDRESS)ARM_CTA15A7_SPC_A7_BX_ADDR0,
+    (EFI_PHYSICAL_ADDRESS)ARM_CTA15A7_SPC_A7_BX_ADDR0,
+    (EFI_PHYSICAL_ADDRESS)ARM_CTA15A7_SPC_A7_BX_ADDR0,
+    (UINT64)0
+  },
+  {
+    // Cluster 1, Core 1
+    0x1, 0x1,
+
+    // MP Core MailBox Set/Get/Clear Addresses and Clear Value
+    (EFI_PHYSICAL_ADDRESS)ARM_CTA15A7_SPC_A7_BX_ADDR1,
+    (EFI_PHYSICAL_ADDRESS)ARM_CTA15A7_SPC_A7_BX_ADDR1,
+    (EFI_PHYSICAL_ADDRESS)ARM_CTA15A7_SPC_A7_BX_ADDR1,
+    (UINT64)0
+  },
+  {
+    // Cluster 1, Core 2
+    0x1, 0x2,
+
+    // MP Core MailBox Set/Get/Clear Addresses and Clear Value
+    (EFI_PHYSICAL_ADDRESS)ARM_CTA15A7_SPC_A7_BX_ADDR2,
+    (EFI_PHYSICAL_ADDRESS)ARM_CTA15A7_SPC_A7_BX_ADDR2,
+    (EFI_PHYSICAL_ADDRESS)ARM_CTA15A7_SPC_A7_BX_ADDR2,
+    (UINT64)0
+  }
+#ifndef ARM_BIGLITTLE_TC2
+  ,{
+    // Cluster 1, Core 3
+    0x1, 0x3,
+
+    // MP Core MailBox Set/Get/Clear Addresses and Clear Value
+    (EFI_PHYSICAL_ADDRESS)ARM_CTA15A7_SPC_A7_BX_ADDR3,
+    (EFI_PHYSICAL_ADDRESS)ARM_CTA15A7_SPC_A7_BX_ADDR3,
+    (EFI_PHYSICAL_ADDRESS)ARM_CTA15A7_SPC_A7_BX_ADDR3,
+    (UINT64)0
+  }
+#endif
+};
+
+/**
+  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
+  )
+{
+  if (MmioRead32(ARM_CTA15A7_SCC_SYSINFO) & ARM_CTA15A7_SCC_SYSINFO_UEFI_RESTORE_DEFAULT_NORFLASH) {
+    return BOOT_WITH_DEFAULT_SETTINGS;
+  } else {
+    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
+  )
+{
+  if (!ArmPlatformIsPrimaryCore (MpId)) {
+    return RETURN_SUCCESS;
+  }
+
+  // Nothing to do here
+
+  return RETURN_SUCCESS;
+}
+
+/**
+  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(mVersatileExpressCTA15A7InfoTable) / sizeof(ARM_CORE_INFO);
+  *ArmCoreTable = mVersatileExpressCTA15A7InfoTable;
+  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/VExpressPkg/Library/ArmVExpressLibCTA15-A7/CTA15-A7Helper.S b/Platform/ARM/VExpressPkg/Library/ArmVExpressLibCTA15-A7/CTA15-A7Helper.S
new file mode 100644
index 000000000000..3719a5ace604
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Library/ArmVExpressLibCTA15-A7/CTA15-A7Helper.S
@@ -0,0 +1,81 @@ 
+//
+//  Copyright (c) 2012-2013, 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>
+
+#include <ArmPlatform.h>
+
+ASM_FUNC(ArmPlatformPeiBootAction)
+  bx    lr
+
+//UINTN
+//ArmPlatformGetCorePosition (
+//  IN UINTN MpId
+//  );
+ASM_FUNC(ArmPlatformGetCorePosition)
+  and   r1, r0, #ARM_CORE_MASK
+  and   r0, r0, #ARM_CLUSTER_MASK
+  add   r0, r1, r0, LSR #7
+  bx    lr
+
+//UINTN
+//ArmPlatformIsPrimaryCore (
+//  IN UINTN MpId
+//  );
+ASM_FUNC(ArmPlatformIsPrimaryCore)
+  // Extract cpu_id and cluster_id from ARM_SCC_CFGREG48
+  // with cpu_id[0:3] and cluster_id[4:7]
+  MOV32 (r1, ARM_CTA15A7_SCC_CFGREG48)
+  ldr   r1, [r1]
+  lsr   r1, #24
+
+  // Shift the SCC value to get the cluster ID at the offset #8
+  lsl   r2, r1, #4
+  and   r2, r2, #0xF00
+
+  // Keep only the cpu ID from the original SCC
+  and   r1, r1, #0x0F
+  // Add the Cluster ID to the Cpu ID
+  orr   r1, r1, r2
+
+  // Keep the Cluster ID and Core ID from the MPID
+  MOV32 (r2, ARM_CLUSTER_MASK | ARM_CORE_MASK)
+  and   r0, r0, r2
+
+  // Compare mpid and boot cpu from ARM_SCC_CFGREG48
+  cmp   r0, r1
+  moveq r0, #1
+  movne r0, #0
+  bx    lr
+
+//UINTN
+//ArmPlatformGetPrimaryCoreMpId (
+//  VOID
+//  );
+ASM_FUNC(ArmPlatformGetPrimaryCoreMpId)
+  // Extract cpu_id and cluster_id from ARM_SCC_CFGREG48
+  // with cpu_id[0:3] and cluster_id[4:7]
+  MOV32 (r0, ARM_CTA15A7_SCC_CFGREG48)
+  ldr   r0, [r0]
+  lsr   r0, #24
+
+  // Shift the SCC value to get the cluster ID at the offset #8
+  lsl   r1, r0, #4
+  and   r1, r1, #0xF00
+
+  // Keep only the cpu ID from the original SCC
+  and   r0, r0, #0x0F
+  // Add the Cluster ID to the Cpu ID
+  orr   r0, r0, r1
+  bx    lr
diff --git a/Platform/ARM/VExpressPkg/Library/ArmVExpressLibCTA15-A7/CTA15-A7Helper.asm b/Platform/ARM/VExpressPkg/Library/ArmVExpressLibCTA15-A7/CTA15-A7Helper.asm
new file mode 100644
index 000000000000..c035843da078
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Library/ArmVExpressLibCTA15-A7/CTA15-A7Helper.asm
@@ -0,0 +1,96 @@ 
+//
+//  Copyright (c) 2012-2013, 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/ArmLib.h>
+
+#include <ArmPlatform.h>
+
+  INCLUDE AsmMacroIoLib.inc
+
+  EXPORT  ArmPlatformPeiBootAction
+  EXPORT  ArmPlatformGetCorePosition
+  EXPORT  ArmPlatformIsPrimaryCore
+  EXPORT  ArmPlatformGetPrimaryCoreMpId
+
+  PRESERVE8
+  AREA    CTA15A7Helper, CODE, READONLY
+
+ArmPlatformPeiBootAction FUNCTION
+  bx    lr
+  ENDFUNC
+
+//UINTN
+//ArmPlatformGetCorePosition (
+//  IN UINTN MpId
+//  );
+ArmPlatformGetCorePosition FUNCTION
+  and   r1, r0, #ARM_CORE_MASK
+  and   r0, r0, #ARM_CLUSTER_MASK
+  add   r0, r1, r0, LSR #7
+  bx    lr
+  ENDFUNC
+
+//UINTN
+//ArmPlatformIsPrimaryCore (
+//  IN UINTN MpId
+//  );
+ArmPlatformIsPrimaryCore FUNCTION
+  // Extract cpu_id and cluster_id from ARM_SCC_CFGREG48
+  // with cpu_id[0:3] and cluster_id[4:7]
+  mov32 r1, ARM_CTA15A7_SCC_CFGREG48
+  ldr   r1, [r1]
+  lsr   r1, #24
+
+  // Shift the SCC value to get the cluster ID at the offset #8
+  lsl   r2, r1, #4
+  and   r2, r2, #0xF00
+
+  // Keep only the cpu ID from the original SCC
+  and   r1, r1, #0x0F
+  // Add the Cluster ID to the Cpu ID
+  orr   r1, r1, r2
+
+  // Keep the Cluster ID and Core ID from the MPID
+  mov32 r2, ARM_CLUSTER_MASK :OR: ARM_CORE_MASK
+  and   r0, r0, r2
+
+  // Compare mpid and boot cpu from ARM_SCC_CFGREG48
+  cmp   r0, r1
+  moveq r0, #1
+  movne r0, #0
+  bx    lr
+  ENDFUNC
+
+//UINTN
+//ArmPlatformGetPrimaryCoreMpId (
+//  VOID
+//  );
+ArmPlatformGetPrimaryCoreMpId FUNCTION
+  // Extract cpu_id and cluster_id from ARM_SCC_CFGREG48
+  // with cpu_id[0:3] and cluster_id[4:7]
+  mov32 r0, ARM_CTA15A7_SCC_CFGREG48
+  ldr   r0, [r0]
+  lsr   r0, #24
+
+  // Shift the SCC value to get the cluster ID at the offset #8
+  lsl   r1, r0, #4
+  and   r1, r1, #0xF00
+
+  // Keep only the cpu ID from the original SCC
+  and   r0, r0, #0x0F
+  // Add the Cluster ID to the Cpu ID
+  orr   r0, r0, r1
+  bx    lr
+  ENDFUNC
+
+  END
diff --git a/Platform/ARM/VExpressPkg/Library/ArmVExpressLibCTA15-A7/CTA15-A7Mem.c b/Platform/ARM/VExpressPkg/Library/ArmVExpressLibCTA15-A7/CTA15-A7Mem.c
new file mode 100644
index 000000000000..4403cbacb881
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Library/ArmVExpressLibCTA15-A7/CTA15-A7Mem.c
@@ -0,0 +1,182 @@ 
+/** @file
+*
+*  Copyright (c) 2012, ARM Limited. All rights reserved.
+*
+*  This program and the accompanying materials
+*  are licensed and made available under the terms and conditions of the BSD License
+*  which accompanies this distribution.  The full text of the license may be found at
+*  http://opensource.org/licenses/bsd-license.php
+*
+*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Library/ArmPlatformLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+
+#include <ArmPlatform.h>
+
+#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS 14
+
+// 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;
+
+  ASSERT (VirtualMemoryMap != NULL);
+
+  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;
+  }
+
+#ifdef ARM_BIGLITTLE_TC2
+  // Secure NOR0 Flash
+  VirtualMemoryTable[Index].PhysicalBase    = ARM_VE_SEC_NOR0_BASE;
+  VirtualMemoryTable[Index].VirtualBase     = ARM_VE_SEC_NOR0_BASE;
+  VirtualMemoryTable[Index].Length          = ARM_VE_SEC_NOR0_SZ;
+  VirtualMemoryTable[Index].Attributes      = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+  // Secure RAM
+  VirtualMemoryTable[++Index].PhysicalBase  = ARM_VE_SEC_RAM0_BASE;
+  VirtualMemoryTable[Index].VirtualBase     = ARM_VE_SEC_RAM0_BASE;
+  VirtualMemoryTable[Index].Length          = ARM_VE_SEC_RAM0_SZ;
+  VirtualMemoryTable[Index].Attributes      = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+#endif
+
+  // 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 CS1 or CS4 - NOR1 Flash
+  VirtualMemoryTable[++Index].PhysicalBase  = ARM_VE_SMB_NOR1_BASE;
+  VirtualMemoryTable[Index].VirtualBase     = ARM_VE_SMB_NOR1_BASE;
+  VirtualMemoryTable[Index].Length          = SIZE_256KB * 255;
+  VirtualMemoryTable[Index].Attributes      = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+  // Environment Variables region
+  VirtualMemoryTable[++Index].PhysicalBase  = ARM_VE_SMB_NOR1_BASE + (SIZE_256KB * 255);
+  VirtualMemoryTable[Index].VirtualBase     = ARM_VE_SMB_NOR1_BASE + (SIZE_256KB * 255);
+  VirtualMemoryTable[Index].Length          = SIZE_64KB * 4;
+  VirtualMemoryTable[Index].Attributes      = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+
+  // SMB CS3 or CS1 - PSRAM
+  VirtualMemoryTable[++Index].PhysicalBase  = ARM_VE_SMB_SRAM_BASE;
+  VirtualMemoryTable[Index].VirtualBase     = ARM_VE_SMB_SRAM_BASE;
+  VirtualMemoryTable[Index].Length          = ARM_VE_SMB_SRAM_SZ;
+  VirtualMemoryTable[Index].Attributes      = CacheAttributes;
+
+  // 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;
+
+#ifdef ARM_BIGLITTLE_TC2
+  // Non-secure ROM
+  VirtualMemoryTable[++Index].PhysicalBase  = ARM_VE_TC2_NON_SECURE_ROM_BASE;
+  VirtualMemoryTable[Index].VirtualBase     = ARM_VE_TC2_NON_SECURE_ROM_BASE;
+  VirtualMemoryTable[Index].Length          = ARM_VE_TC2_NON_SECURE_ROM_SZ;
+  VirtualMemoryTable[Index].Attributes      = CacheAttributes;
+#endif
+
+  // OnChip peripherals
+  VirtualMemoryTable[++Index].PhysicalBase  = ARM_VE_ONCHIP_PERIPH_BASE;
+  VirtualMemoryTable[Index].VirtualBase     = ARM_VE_ONCHIP_PERIPH_BASE;
+  VirtualMemoryTable[Index].Length          = ARM_VE_ONCHIP_PERIPH_SZ;
+  VirtualMemoryTable[Index].Attributes      = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+
+  // SCC Region
+  VirtualMemoryTable[++Index].PhysicalBase  = ARM_CTA15A7_SCC_BASE;
+  VirtualMemoryTable[Index].VirtualBase     = ARM_CTA15A7_SCC_BASE;
+  VirtualMemoryTable[Index].Length          = SIZE_64KB;
+  VirtualMemoryTable[Index].Attributes      = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+
+#ifdef ARM_BIGLITTLE_TC2
+  // TC2 OnChip non-secure SRAM
+  VirtualMemoryTable[++Index].PhysicalBase  = ARM_VE_TC2_NON_SECURE_SRAM_BASE;
+  VirtualMemoryTable[Index].VirtualBase     = ARM_VE_TC2_NON_SECURE_SRAM_BASE;
+  VirtualMemoryTable[Index].Length          = ARM_VE_TC2_NON_SECURE_SRAM_SZ;
+  VirtualMemoryTable[Index].Attributes      = CacheAttributes;
+#endif
+
+#ifndef ARM_BIGLITTLE_TC2
+  // Workaround for SRAM bug in RTSM
+  if (PcdGet64 (PcdSystemMemoryBase) != 0x80000000) {
+    VirtualMemoryTable[++Index].PhysicalBase  = 0x80000000;
+    VirtualMemoryTable[Index].VirtualBase     = 0x80000000;
+    VirtualMemoryTable[Index].Length          = PcdGet64 (PcdSystemMemoryBase) - 0x80000000;
+    VirtualMemoryTable[Index].Attributes      = CacheAttributes;
+  }
+#endif
+
+  // DDR
+  VirtualMemoryTable[++Index].PhysicalBase  = PcdGet64 (PcdSystemMemoryBase);
+  VirtualMemoryTable[Index].VirtualBase     = PcdGet64 (PcdSystemMemoryBase);
+  VirtualMemoryTable[Index].Length          = PcdGet64 (PcdSystemMemorySize);
+  VirtualMemoryTable[Index].Attributes      = CacheAttributes;
+
+  // Detect if it is a 1GB or 2GB Test Chip
+  //   [16:19]: 0=1GB TC2, 1=2GB TC2
+  if (MmioRead32(ARM_VE_SYS_PROCID0_REG) & (0xF << 16)) {
+    DEBUG((EFI_D_ERROR,"Info: 2GB Test Chip 2 detected.\n"));
+    BuildResourceDescriptorHob (
+        EFI_RESOURCE_SYSTEM_MEMORY,
+        EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+          EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
+          EFI_RESOURCE_ATTRIBUTE_TESTED,
+        PcdGet64 (PcdSystemMemoryBase) + PcdGet64 (PcdSystemMemorySize),
+        SIZE_1GB
+    );
+
+    // Map the additional 1GB into the MMU
+    VirtualMemoryTable[++Index].PhysicalBase  = PcdGet64 (PcdSystemMemoryBase) + PcdGet64 (PcdSystemMemorySize);
+    VirtualMemoryTable[Index].VirtualBase     = PcdGet64 (PcdSystemMemoryBase) + PcdGet64 (PcdSystemMemorySize);
+    VirtualMemoryTable[Index].Length          = SIZE_1GB;
+    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/VExpressPkg/Library/ArmVExpressLibRTSM/AArch64/RTSMHelper.S b/Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/AArch64/RTSMHelper.S
new file mode 100644
index 000000000000..db6d83c3cce9
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/AArch64/RTSMHelper.S
@@ -0,0 +1,61 @@ 
+#
+#  Copyright (c) 2011-2013, 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>
+
+ASM_FUNC(ArmPlatformPeiBootAction)
+  ret
+
+//UINTN
+//ArmPlatformGetPrimaryCoreMpId (
+//  VOID
+//  );
+ASM_FUNC(ArmPlatformGetPrimaryCoreMpId)
+  MOV32  (w0, FixedPcdGet32 (PcdArmPrimaryCore))
+  ret
+
+# IN None
+# OUT x0 = number of cores present in the system
+ASM_FUNC(ArmGetCpuCountPerCluster)
+  MOV32  (w0, FixedPcdGet32 (PcdCoreCount))
+  ret
+
+//UINTN
+//ArmPlatformIsPrimaryCore (
+//  IN UINTN MpId
+//  );
+ASM_FUNC(ArmPlatformIsPrimaryCore)
+  MOV32  (w1, FixedPcdGet32 (PcdArmPrimaryCoreMask))
+  and   x0, x0, x1
+  MOV32  (w1, FixedPcdGet32 (PcdArmPrimaryCore))
+  cmp   w0, w1
+  b.ne  1f
+  mov   x0, #1
+  ret
+1:
+  mov   x0, #0
+  ret
+
+//UINTN
+//ArmPlatformGetCorePosition (
+//  IN UINTN MpId
+//  );
+// With this function: CorePos = (ClusterId * 4) + CoreId
+ASM_FUNC(ArmPlatformGetCorePosition)
+  and   x1, x0, #ARM_CORE_MASK
+  and   x0, x0, #ARM_CLUSTER_MASK
+  add   x0, x1, x0, LSR #6
+  ret
+
+ASM_FUNCTION_REMOVE_IF_UNREFERENCED
diff --git a/Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/Arm/RTSMHelper.S b/Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/Arm/RTSMHelper.S
new file mode 100644
index 000000000000..35743b08dc88
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/Arm/RTSMHelper.S
@@ -0,0 +1,97 @@ 
+#
+#  Copyright (c) 2011-2013, 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>
+
+#include <Chipset/ArmCortexA9.h>
+
+ASM_FUNC(ArmPlatformPeiBootAction)
+  bx    lr
+
+# IN None
+# OUT r0 = SCU Base Address
+ASM_FUNC(ArmGetScuBaseAddress)
+  # Read Configuration Base Address Register. ArmCBar cannot be called to get
+  # the Configuration BAR as a stack is not necessary setup. The SCU is at the
+  # offset 0x0000 from the Private Memory Region.
+  mrc   p15, 4, r0, c15, c0, 0
+  bx    lr
+
+//UINTN
+//ArmPlatformGetPrimaryCoreMpId (
+//  VOID
+//  );
+ASM_FUNC(ArmPlatformGetPrimaryCoreMpId)
+  MOV32  (r0, FixedPcdGet32 (PcdArmPrimaryCore))
+  bx    lr
+
+# IN None
+# OUT r0 = number of cores present in the system
+ASM_FUNC(ArmGetCpuCountPerCluster)
+  stmfd SP!, {r1-r2}
+
+  # Read CP15 MIDR
+  mrc   p15, 0, r1, c0, c0, 0
+
+  # Check if the CPU is A15
+  mov   r1, r1, LSR #4
+  MOV32 (r0, ARM_CPU_TYPE_MASK)
+  and   r1, r1, r0
+
+  MOV32 (r0, ARM_CPU_TYPE_A15)
+  cmp   r1, r0
+  beq   _Read_cp15_reg
+
+_CPU_is_not_A15:
+  mov   r2, lr                           @ Save link register
+  bl    ArmGetScuBaseAddress             @ Read SCU Base Address
+  mov   lr, r2                           @ Restore link register val
+  ldr   r0, [r0, #A9_SCU_CONFIG_OFFSET]     @ Read SCU Config reg to get CPU count
+  b     _Return
+
+_Read_cp15_reg:
+  mrc   p15, 1, r0, c9, c0, 2            @ Read C9 register of CP15 to get CPU count
+  lsr   r0, #24
+
+_Return:
+  and   r0, r0, #3
+  # Add '1' to the number of CPU on the Cluster
+  add   r0, r0, #1
+  ldmfd SP!, {r1-r2}
+  bx lr
+
+//UINTN
+//ArmPlatformIsPrimaryCore (
+//  IN UINTN MpId
+//  );
+ASM_FUNC(ArmPlatformIsPrimaryCore)
+  MOV32  (r1, FixedPcdGet32 (PcdArmPrimaryCoreMask))
+  and   r0, r0, r1
+  MOV32  (r1, FixedPcdGet32 (PcdArmPrimaryCore))
+  cmp   r0, r1
+  moveq r0, #1
+  movne r0, #0
+  bx    lr
+
+//UINTN
+//ArmPlatformGetCorePosition (
+//  IN UINTN MpId
+//  );
+ASM_FUNC(ArmPlatformGetCorePosition)
+  and   r1, r0, #ARM_CORE_MASK
+  and   r0, r0, #ARM_CLUSTER_MASK
+  add   r0, r1, r0, LSR #7
+  bx    lr
+
+ASM_FUNCTION_REMOVE_IF_UNREFERENCED
diff --git a/Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/Arm/RTSMHelper.asm b/Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/Arm/RTSMHelper.asm
new file mode 100644
index 000000000000..66068e6595db
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/Arm/RTSMHelper.asm
@@ -0,0 +1,118 @@ 
+//
+//  Copyright (c) 2011-2013, 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 <Base.h>
+#include <Library/ArmLib.h>
+#include <Library/PcdLib.h>
+
+#include <Chipset/ArmCortexA9.h>
+
+#include <AutoGen.h>
+
+  INCLUDE AsmMacroIoLib.inc
+
+  EXPORT    ArmPlatformPeiBootAction
+  EXPORT    ArmGetCpuCountPerCluster
+  EXPORT    ArmPlatformIsPrimaryCore
+  EXPORT    ArmPlatformGetPrimaryCoreMpId
+  EXPORT    ArmPlatformGetCorePosition
+
+  AREA RTSMHelper, CODE, READONLY
+
+ArmPlatformPeiBootAction FUNCTION
+  bx    lr
+  ENDFUNC
+
+// IN None
+// OUT r0 = SCU Base Address
+ArmGetScuBaseAddress FUNCTION
+  // Read Configuration Base Address Register. ArmCBar cannot be called to get
+  // the Configuration BAR as a stack is not necessary setup. The SCU is at the
+  // offset 0x0000 from the Private Memory Region.
+  mrc   p15, 4, r0, c15, c0, 0
+  bx  lr
+  ENDFUNC
+
+//UINTN
+//ArmPlatformGetPrimaryCoreMpId (
+//  VOID
+//  );
+ArmPlatformGetPrimaryCoreMpId FUNCTION
+  mov32 r0, FixedPcdGet32(PcdArmPrimaryCore)
+  bx    lr
+  ENDFUNC
+
+// IN None
+// OUT r0 = number of cores present in the system
+ArmGetCpuCountPerCluster FUNCTION
+  stmfd SP!, {r1-r2}
+
+  // Read CP15 MIDR
+  mrc   p15, 0, r1, c0, c0, 0
+
+  // Check if the CPU is A15
+  mov   r1, r1, LSR #4
+  mov   r0, #ARM_CPU_TYPE_MASK
+  and   r1, r1, r0
+
+  mov   r0, #ARM_CPU_TYPE_A15
+  cmp   r1, r0
+  beq   _Read_cp15_reg
+
+_CPU_is_not_A15
+  mov   r2, lr                              ; Save link register
+  bl    ArmGetScuBaseAddress                ; Read SCU Base Address
+  mov   lr, r2                              ; Restore link register val
+  ldr   r0, [r0, #A9_SCU_CONFIG_OFFSET]     ; Read SCU Config reg to get CPU count
+  b     _Return
+
+_Read_cp15_reg
+  mrc   p15, 1, r0, c9, c0, 2            ; Read C9 register of CP15 to get CPU count
+  lsr   r0, #24
+
+
+_Return
+  and   r0, r0, #3
+  // Add '1' to the number of CPU on the Cluster
+  add   r0, r0, #1
+  ldmfd SP!, {r1-r2}
+  bx lr
+  ENDFUNC
+
+//UINTN
+//ArmPlatformIsPrimaryCore (
+//  IN UINTN MpId
+//  );
+ArmPlatformIsPrimaryCore FUNCTION
+  mov32 r1, FixedPcdGet32(PcdArmPrimaryCoreMask)
+  and   r0, r0, r1
+  mov32 r1, FixedPcdGet32(PcdArmPrimaryCore)
+  ldr   r1, [r1]
+  cmp   r0, r1
+  moveq r0, #1
+  movne r0, #0
+  bx    lr
+  ENDFUNC
+
+//UINTN
+//ArmPlatformGetCorePosition (
+//  IN UINTN MpId
+//  );
+ArmPlatformGetCorePosition FUNCTION
+  and   r1, r0, #ARM_CORE_MASK
+  and   r0, r0, #ARM_CLUSTER_MASK
+  add   r0, r1, r0, LSR #7
+  bx    lr
+  ENDFUNC
+
+  END
diff --git a/Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/ArmVExpressLib.inf b/Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/ArmVExpressLib.inf
new file mode 100644
index 000000000000..2322ee6a2cc5
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/ArmVExpressLib.inf
@@ -0,0 +1,63 @@ 
+#/* @file
+#  Copyright (c) 2011-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.
+#
+#*/
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = RTSMArmVExpressLib
+  FILE_GUID                      = b98a6cb7-d472-4128-ad62-a7347f85ce13
+  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/VExpressPkg/ArmVExpressPkg.dec
+
+[LibraryClasses]
+  IoLib
+  ArmLib
+  MemoryAllocationLib
+  SerialPortLib
+  HobLib
+
+[Sources.common]
+  RTSM.c
+  RTSMMem.c
+
+[Sources.ARM]
+  Arm/RTSMHelper.asm    | RVCT
+  Arm/RTSMHelper.S      | GCC
+
+[Sources.AARCH64]
+  AArch64/RTSMHelper.S
+
+[FeaturePcd]
+  gEmbeddedTokenSpaceGuid.PcdCacheEnable
+  gArmPlatformTokenSpaceGuid.PcdNorFlashRemapping
+
+[FixedPcd]
+  gArmTokenSpaceGuid.PcdSystemMemoryBase
+  gArmTokenSpaceGuid.PcdSystemMemorySize
+  gArmTokenSpaceGuid.PcdFvBaseAddress
+
+  gArmTokenSpaceGuid.PcdArmPrimaryCoreMask
+  gArmTokenSpaceGuid.PcdArmPrimaryCore
+
+  gArmPlatformTokenSpaceGuid.PcdCoreCount
+
+[Ppis]
+  gArmMpCoreInfoPpiGuid
diff --git a/Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/ArmVExpressLibSec.inf b/Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/ArmVExpressLibSec.inf
new file mode 100644
index 000000000000..e659f44ad232
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/ArmVExpressLibSec.inf
@@ -0,0 +1,59 @@ 
+#/* @file
+#  Copyright (c) 2011-2012, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#*/
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = RTSMArmVExpressLibSec
+  FILE_GUID                      = a79eed97-4b98-4974-9690-37b32d6a5b56
+  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
+
+[LibraryClasses]
+  IoLib
+  ArmLib
+  SerialPortLib
+
+[Sources.common]
+  RTSM.c
+
+[Sources.ARM]
+  Arm/RTSMHelper.asm    | RVCT
+  Arm/RTSMHelper.S      | GCC
+
+[Sources.AARCH64]
+  AArch64/RTSMHelper.S
+
+[FeaturePcd]
+  gEmbeddedTokenSpaceGuid.PcdCacheEnable
+  gArmPlatformTokenSpaceGuid.PcdNorFlashRemapping
+
+[FixedPcd]
+  gArmTokenSpaceGuid.PcdSystemMemoryBase
+  gArmTokenSpaceGuid.PcdSystemMemorySize
+  gArmTokenSpaceGuid.PcdFvBaseAddress
+
+  gArmTokenSpaceGuid.PcdArmPrimaryCoreMask
+  gArmTokenSpaceGuid.PcdArmPrimaryCore
+
+  gArmPlatformTokenSpaceGuid.PcdCoreCount
+
+[Ppis]
+  gArmMpCoreInfoPpiGuid
diff --git a/Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/RTSM.c b/Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/RTSM.c
new file mode 100644
index 000000000000..11dd7ff1bfb0
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/RTSM.c
@@ -0,0 +1,209 @@ 
+/** @file
+*
+*  Copyright (c) 2011-2013, 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/IoLib.h>
+#include <Library/ArmPlatformLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+
+#include <Ppi/ArmMpCoreInfo.h>
+
+#include <ArmPlatform.h>
+
+/**
+  Return the core per cluster. The method may differ per core type
+
+  This function might be called from assembler before any stack is set.
+
+  @return   Return the core count per cluster
+
+**/
+UINTN
+ArmGetCpuCountPerCluster (
+  VOID
+  );
+
+ARM_CORE_INFO mVersatileExpressMpCoreInfoTable[] = {
+  {
+    // 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 0, Core 2
+    0x0, 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 0, Core 3
+    0x0, 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
+  },
+  {
+    // 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
+  )
+{
+  if (!ArmPlatformIsPrimaryCore (MpId)) {
+    return RETURN_SUCCESS;
+  }
+
+  // Disable memory remapping and return to normal mapping
+  MmioOr32 (SP810_CTRL_BASE, BIT8);
+
+  return RETURN_SUCCESS;
+}
+
+/**
+  Initialize the system (or sometimes called permanent) memory
+
+  This memory is generally represented by the DRAM.
+
+**/
+VOID
+ArmPlatformInitializeSystemMemory (
+  VOID
+  )
+{
+  // Nothing to do here
+}
+
+EFI_STATUS
+PrePeiCoreGetMpCoreInfo (
+  OUT UINTN                   *CoreCount,
+  OUT ARM_CORE_INFO           **ArmCoreTable
+  )
+{
+  UINT32   ProcType;
+
+  ProcType = MmioRead32 (ARM_VE_SYS_PROCID0_REG) & ARM_VE_SYS_PROC_ID_MASK;
+  if ((ProcType == ARM_VE_SYS_PROC_ID_CORTEX_A9) || (ProcType == ARM_VE_SYS_PROC_ID_CORTEX_A15)) {
+    // Only support one cluster on all but ARMv8 FVP platform. FVP still uses CortexA9 ID.
+    *CoreCount    = ArmGetCpuCountPerCluster ();
+    *ArmCoreTable = mVersatileExpressMpCoreInfoTable;
+    return EFI_SUCCESS;
+  } else {
+    return EFI_UNSUPPORTED;
+  }
+}
+
+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/VExpressPkg/Library/ArmVExpressLibRTSM/RTSMMem.c b/Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/RTSMMem.c
new file mode 100644
index 000000000000..6379e81751fc
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Library/ArmVExpressLibRTSM/RTSMMem.c
@@ -0,0 +1,161 @@ 
+/** @file
+*
+*  Copyright (c) 2011-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 <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>
+
+// Number of Virtual Memory Map Descriptors
+#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS          9
+
+// 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;
+  EFI_RESOURCE_ATTRIBUTE_TYPE   ResourceAttributes;
+  UINTN                         Index = 0;
+  ARM_MEMORY_REGION_DESCRIPTOR  *VirtualMemoryTable;
+  UINT32                        SysId;
+  BOOLEAN                       HasSparseMemory;
+  EFI_VIRTUAL_ADDRESS           SparseMemoryBase;
+  UINT64                        SparseMemorySize;
+
+  ASSERT (VirtualMemoryMap != NULL);
+
+  // The FVP model has Sparse memory
+  SysId = MmioRead32 (ARM_VE_SYS_ID_REG);
+  if (SysId != ARM_RTSM_SYS_ID) {
+    HasSparseMemory = TRUE;
+
+    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;
+
+    // Declared the additional DRAM from 2GB to 4GB
+    SparseMemoryBase = 0x0880000000;
+    SparseMemorySize = SIZE_2GB;
+
+    BuildResourceDescriptorHob (
+        EFI_RESOURCE_SYSTEM_MEMORY,
+        ResourceAttributes,
+        SparseMemoryBase,
+        SparseMemorySize);
+  } else {
+    HasSparseMemory = FALSE;
+    SparseMemoryBase = 0x0;
+    SparseMemorySize = 0x0;
+  }
+
+  VirtualMemoryTable = (ARM_MEMORY_REGION_DESCRIPTOR*)
+    AllocatePages (EFI_SIZE_TO_PAGES (sizeof(ARM_MEMORY_REGION_DESCRIPTOR)
+                                      * MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS));
+  if (VirtualMemoryTable == NULL) {
+    return;
+  }
+
+  CacheAttributes = (FeaturePcdGet(PcdCacheEnable))
+                    ? DDR_ATTRIBUTES_CACHED
+                    : DDR_ATTRIBUTES_UNCACHED;
+
+  // ReMap (Either NOR Flash or DRAM)
+  VirtualMemoryTable[Index].PhysicalBase = ARM_VE_REMAP_BASE;
+  VirtualMemoryTable[Index].VirtualBase = ARM_VE_REMAP_BASE;
+  VirtualMemoryTable[Index].Length = ARM_VE_REMAP_SZ;
+  VirtualMemoryTable[Index].Attributes = CacheAttributes;
+
+  // DDR
+  VirtualMemoryTable[++Index].PhysicalBase = ARM_VE_DRAM_BASE;
+  VirtualMemoryTable[Index].VirtualBase = ARM_VE_DRAM_BASE;
+  VirtualMemoryTable[Index].Length = ARM_VE_DRAM_SZ;
+  VirtualMemoryTable[Index].Attributes = CacheAttributes;
+
+  // CPU peripherals. TRM. Manual says not all of them are implemented.
+  VirtualMemoryTable[++Index].PhysicalBase = ARM_VE_ON_CHIP_PERIPH_BASE;
+  VirtualMemoryTable[Index].VirtualBase = ARM_VE_ON_CHIP_PERIPH_BASE;
+  VirtualMemoryTable[Index].Length = ARM_VE_ON_CHIP_PERIPH_SZ;
+  VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+
+  // SMB CS0-CS1 - NOR Flash 1 & 2
+  VirtualMemoryTable[++Index].PhysicalBase = ARM_VE_SMB_NOR0_BASE;
+  VirtualMemoryTable[Index].VirtualBase = ARM_VE_SMB_NOR0_BASE;
+  VirtualMemoryTable[Index].Length = ARM_VE_SMB_NOR0_SZ + ARM_VE_SMB_NOR1_SZ;
+  VirtualMemoryTable[Index].Attributes = CacheAttributes;
+
+  // SMB CS2 - SRAM
+  VirtualMemoryTable[++Index].PhysicalBase = ARM_VE_SMB_SRAM_BASE;
+  VirtualMemoryTable[Index].VirtualBase = ARM_VE_SMB_SRAM_BASE;
+  VirtualMemoryTable[Index].Length = ARM_VE_SMB_SRAM_SZ;
+  VirtualMemoryTable[Index].Attributes = CacheAttributes;
+
+  // Peripheral CS2 and CS3
+  VirtualMemoryTable[++Index].PhysicalBase = ARM_VE_SMB_PERIPH_BASE;
+  VirtualMemoryTable[Index].VirtualBase = ARM_VE_SMB_PERIPH_BASE;
+  VirtualMemoryTable[Index].Length = 2 * ARM_VE_SMB_PERIPH_SZ;
+  VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+
+  // VRAM
+  VirtualMemoryTable[++Index].PhysicalBase = PL111_CLCD_VRAM_MOTHERBOARD_BASE;
+  VirtualMemoryTable[Index].VirtualBase = PL111_CLCD_VRAM_MOTHERBOARD_BASE;
+  VirtualMemoryTable[Index].Length = PL111_CLCD_VRAM_MOTHERBOARD_SIZE;
+  //
+  // Map the VRAM region as Normal Non-Cacheable memory and not device memory,
+  // so that we can use the accelerated string routines that may use unaligned
+  // accesses or DC ZVA instructions. The enum identifier is slightly awkward
+  // here, but it maps to a memory type that allows buffering and reordering.
+  //
+  VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED;
+
+  // Map sparse memory region if present
+  if (HasSparseMemory) {
+    VirtualMemoryTable[++Index].PhysicalBase = SparseMemoryBase;
+    VirtualMemoryTable[Index].VirtualBase = SparseMemoryBase;
+    VirtualMemoryTable[Index].Length = SparseMemorySize;
+    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 < MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS);
+  *VirtualMemoryMap = VirtualMemoryTable;
+}
diff --git a/Platform/ARM/VExpressPkg/Library/ArmVExpressSysConfigLib/ArmVExpressSysConfig.c b/Platform/ARM/VExpressPkg/Library/ArmVExpressSysConfigLib/ArmVExpressSysConfig.c
new file mode 100644
index 000000000000..6dfbacd11762
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Library/ArmVExpressSysConfigLib/ArmVExpressSysConfig.c
@@ -0,0 +1,273 @@ 
+/** @file  ArmVExpressSysConfig.c
+
+  Copyright (c) 2011-2012, 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 <Base.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+
+#include <Library/ArmPlatformSysConfigLib.h>
+#include <ArmPlatform.h>
+
+//
+// SYS_CFGCTRL Bits
+//
+#define SYS_CFGCTRL_START                 BIT31
+#define SYS_CFGCTRL_READ                  (0 << 30)
+#define SYS_CFGCTRL_WRITE                 (1 << 30)
+#define SYS_CFGCTRL_FUNCTION(fun)         (((fun ) &  0x3F) << 20)
+#define SYS_CFGCTRL_SITE(site)            (((site) &   0x3) << 16)
+#define SYS_CFGCTRL_POSITION(pos)         (((pos ) &   0xF) << 12)
+#define SYS_CFGCTRL_DEVICE(dev)            ((dev ) & 0xFFF)
+
+//
+// SYS_CFGSTAT Bits
+//
+#define SYS_CFGSTAT_ERROR                 BIT1
+#define SYS_CFGSTAT_COMPLETE              BIT0
+
+/****************************************************************************
+ *
+ *  This file makes it easier to access the System Configuration Registers
+ *  in the ARM Versatile Express motherboard.
+ *
+ ****************************************************************************/
+
+RETURN_STATUS
+ArmPlatformSysConfigInitialize (
+  VOID
+  )
+{
+  return RETURN_SUCCESS;
+}
+
+/***************************************
+ * GENERAL FUNCTION: AccessSysCfgRegister
+ * Interacts with
+ *    SYS_CFGSTAT
+ *    SYS_CFGDATA
+ *    SYS_CFGCTRL
+ * for setting and for reading out values
+ ***************************************/
+
+RETURN_STATUS
+AccessSysCfgRegister (
+  IN     UINT32   ReadWrite,
+  IN     UINT32   Function,
+  IN     UINT32   Site,
+  IN     UINT32   Position,
+  IN     UINT32   Device,
+  IN OUT UINT32*  Data
+  )
+{
+  UINT32          SysCfgCtrl;
+
+  // Clear the COMPLETE bit
+  MmioAnd32(ARM_VE_SYS_CFGSTAT_REG, ~SYS_CFGSTAT_COMPLETE);
+
+  // If writing, then set the data value
+  if(ReadWrite == SYS_CFGCTRL_WRITE) {
+    MmioWrite32(ARM_VE_SYS_CFGDATA_REG, *Data);
+  }
+
+  // Set the control value
+  SysCfgCtrl = SYS_CFGCTRL_START | ReadWrite | SYS_CFGCTRL_FUNCTION(Function) | SYS_CFGCTRL_SITE(Site) |
+      SYS_CFGCTRL_POSITION(Position) | SYS_CFGCTRL_DEVICE(Device);
+  MmioWrite32(ARM_VE_SYS_CFGCTRL_REG, SysCfgCtrl);
+
+  // Wait until the COMPLETE bit is set
+  while ((MmioRead32(ARM_VE_SYS_CFGSTAT_REG) & SYS_CFGSTAT_COMPLETE) == 0);
+
+  // Check for errors
+  if(MmioRead32(ARM_VE_SYS_CFGSTAT_REG) & SYS_CFGSTAT_ERROR) {
+    return RETURN_DEVICE_ERROR;
+  }
+
+  // If reading then get the data value
+  if(ReadWrite == SYS_CFGCTRL_READ) {
+    *Data = MmioRead32(ARM_VE_SYS_CFGDATA_REG);
+  }
+
+  return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+ArmPlatformSysConfigGet (
+  IN  SYS_CONFIG_FUNCTION   Function,
+  OUT UINT32*               Value
+  )
+{
+  UINT32          Site;
+  UINT32          Position;
+  UINT32          Device;
+
+  Position = 0;
+  Device = 0;
+
+  // Intercept some functions
+  switch(Function) {
+
+  case SYS_CFG_OSC_SITE1:
+    Function = SYS_CFG_OSC;
+    Site = ARM_VE_DAUGHTERBOARD_1_SITE;
+    break;
+
+  case SYS_CFG_OSC_SITE2:
+    Function = SYS_CFG_OSC;
+    Site = ARM_VE_DAUGHTERBOARD_2_SITE;
+    break;
+
+  case SYS_CFG_MUXFPGA:
+    Site = *Value;
+    break;
+
+  case SYS_CFG_OSC:
+  case SYS_CFG_VOLT:
+  case SYS_CFG_AMP:
+  case SYS_CFG_TEMP:
+  case SYS_CFG_RESET:
+  case SYS_CFG_SCC:
+  case SYS_CFG_DVIMODE:
+  case SYS_CFG_POWER:
+    Site = ARM_VE_MOTHERBOARD_SITE;
+    break;
+
+  case SYS_CFG_SHUTDOWN:
+  case SYS_CFG_REBOOT:
+  case SYS_CFG_RTC:
+  default:
+    return RETURN_UNSUPPORTED;
+  }
+
+  return AccessSysCfgRegister (SYS_CFGCTRL_READ, Function, Site, Position, Device, Value);
+}
+
+RETURN_STATUS
+ArmPlatformSysConfigGetValues (
+  IN  SYS_CONFIG_FUNCTION   Function,
+  IN  UINTN                 Size,
+  OUT UINT32*               Values
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
+
+RETURN_STATUS
+ArmPlatformSysConfigSet (
+  IN  SYS_CONFIG_FUNCTION   Function,
+  IN  UINT32                Value
+  )
+{
+  UINT32          Site;
+  UINT32          Position;
+  UINT32          Device;
+
+  Position = 0;
+  Device = 0;
+
+  // Intercept some functions
+  switch(Function) {
+
+  case SYS_CFG_OSC_SITE1:
+    Function = SYS_CFG_OSC;
+    Site = ARM_VE_DAUGHTERBOARD_1_SITE;
+    break;
+
+  case SYS_CFG_OSC_SITE2:
+    Function = SYS_CFG_OSC;
+    Site = ARM_VE_DAUGHTERBOARD_2_SITE;
+    break;
+
+  case SYS_CFG_MUXFPGA:
+    Site = Value;
+    break;
+
+  case SYS_CFG_RESET:
+  case SYS_CFG_SCC:
+  case SYS_CFG_SHUTDOWN:
+  case SYS_CFG_REBOOT:
+  case SYS_CFG_DVIMODE:
+  case SYS_CFG_POWER:
+    Site = ARM_VE_MOTHERBOARD_SITE;
+    break;
+
+  case SYS_CFG_OSC:
+  case SYS_CFG_VOLT:
+  case SYS_CFG_AMP:
+  case SYS_CFG_TEMP:
+  case SYS_CFG_RTC:
+  default:
+    return RETURN_UNSUPPORTED;
+  }
+
+  return AccessSysCfgRegister (SYS_CFGCTRL_WRITE, Function, Site, Position, Device, &Value);
+}
+
+RETURN_STATUS
+ArmPlatformSysConfigSetDevice (
+  IN  SYS_CONFIG_FUNCTION   Function,
+  IN  UINT32                Device,
+  IN  UINT32                Value
+  )
+{
+  UINT32          Site;
+  UINT32          Position;
+
+  Position = 0;
+
+  // Intercept some functions
+  switch(Function) {
+  case SYS_CFG_SCC:
+#ifdef ARM_VE_SCC_BASE
+    MmioWrite32 ((ARM_VE_SCC_BASE + (Device * 4)),Value);
+    return RETURN_SUCCESS;
+#else
+    // There is no System Configuration Controller on the Model
+    return RETURN_UNSUPPORTED;
+#endif
+
+  case SYS_CFG_OSC_SITE1:
+    Function = SYS_CFG_OSC;
+    Site = ARM_VE_DAUGHTERBOARD_1_SITE;
+    break;
+
+  case SYS_CFG_OSC_SITE2:
+    Function = SYS_CFG_OSC;
+    Site = ARM_VE_DAUGHTERBOARD_2_SITE;
+    break;
+
+  case SYS_CFG_MUXFPGA:
+    Site = Value;
+    break;
+
+  case SYS_CFG_RTC:
+    return RETURN_UNSUPPORTED;
+    //break;
+
+  case SYS_CFG_OSC:
+  case SYS_CFG_VOLT:
+  case SYS_CFG_AMP:
+  case SYS_CFG_TEMP:
+  case SYS_CFG_RESET:
+  case SYS_CFG_SHUTDOWN:
+  case SYS_CFG_REBOOT:
+  case SYS_CFG_DVIMODE:
+  case SYS_CFG_POWER:
+    Site = ARM_VE_MOTHERBOARD_SITE;
+    break;
+  default:
+    return RETURN_UNSUPPORTED;
+  }
+
+  return AccessSysCfgRegister (SYS_CFGCTRL_WRITE, Function, Site, Position, Device, &Value);
+}
diff --git a/Platform/ARM/VExpressPkg/Library/ArmVExpressSysConfigLib/ArmVExpressSysConfigLib.inf b/Platform/ARM/VExpressPkg/Library/ArmVExpressSysConfigLib/ArmVExpressSysConfigLib.inf
new file mode 100644
index 000000000000..c400ab831ab1
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Library/ArmVExpressSysConfigLib/ArmVExpressSysConfigLib.inf
@@ -0,0 +1,35 @@ 
+#/** @file
+#
+#  Component description file for ArmVExpressSysConfigLib module
+#
+#  Copyright (c) 2011-2012, 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                      = ArmVExpressSysConfigLib
+  FILE_GUID                      = a05b5cc0-82d2-11e0-82cb-0002a5d5c51b
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = ArmPlatformSysConfigLib|SEC DXE_DRIVER
+
+[Sources.common]
+  ArmVExpressSysConfig.c
+
+[Packages]
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  MdePkg/MdePkg.dec
+  Platform/ARM/VExpressPkg/ArmVExpressPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  IoLib
diff --git a/Platform/ARM/VExpressPkg/Library/ArmVExpressSysConfigRuntimeLib/ArmVExpressSysConfigRuntimeLib.c b/Platform/ARM/VExpressPkg/Library/ArmVExpressSysConfigRuntimeLib/ArmVExpressSysConfigRuntimeLib.c
new file mode 100644
index 000000000000..1f915e3b0225
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Library/ArmVExpressSysConfigRuntimeLib/ArmVExpressSysConfigRuntimeLib.c
@@ -0,0 +1,283 @@ 
+/** @file  ArmVExpressSysConfig.c
+
+  Copyright (c) 2011-2012, 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 <Base.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+
+#include <Library/ArmPlatformSysConfigLib.h>
+#include <ArmPlatform.h>
+
+#include <Uefi.h>
+#include <Library/UefiRuntimeLib.h>
+
+//
+// SYS_CFGCTRL Bits
+//
+#define SYS_CFGCTRL_START                 BIT31
+#define SYS_CFGCTRL_READ                  (0 << 30)
+#define SYS_CFGCTRL_WRITE                 (1 << 30)
+#define SYS_CFGCTRL_FUNCTION(fun)         (((fun ) &  0x3F) << 20)
+#define SYS_CFGCTRL_SITE(site)            (((site) &   0x3) << 16)
+#define SYS_CFGCTRL_POSITION(pos)         (((pos ) &   0xF) << 12)
+#define SYS_CFGCTRL_DEVICE(dev)            ((dev ) & 0xFFF)
+
+//
+// SYS_CFGSTAT Bits
+//
+#define SYS_CFGSTAT_ERROR                 BIT1
+#define SYS_CFGSTAT_COMPLETE              BIT0
+
+/****************************************************************************
+ *
+ *  This file makes it easier to access the System Configuration Registers
+ *  in the ARM Versatile Express motherboard.
+ *
+ ****************************************************************************/
+
+RETURN_STATUS
+ArmPlatformSysConfigInitialize (
+  VOID
+  )
+{
+  return RETURN_SUCCESS;
+}
+
+/***************************************
+ * GENERAL FUNCTION: AccessSysCfgRegister
+ * Interacts with
+ *    SYS_CFGSTAT
+ *    SYS_CFGDATA
+ *    SYS_CFGCTRL
+ * for setting and for reading out values
+ ***************************************/
+
+RETURN_STATUS
+AccessSysCfgRegister (
+  IN     UINT32   ReadWrite,
+  IN     UINT32   Function,
+  IN     UINT32   Site,
+  IN     UINT32   Position,
+  IN     UINT32   Device,
+  IN OUT UINT32*  Data
+  )
+{
+  UINT32          SysCfgCtrl;
+
+  if (EfiAtRuntime ()) {
+    return RETURN_UNSUPPORTED;
+  }
+
+  // Clear the COMPLETE bit
+  MmioAnd32(ARM_VE_SYS_CFGSTAT_REG, ~SYS_CFGSTAT_COMPLETE);
+
+  // If writing, then set the data value
+  if(ReadWrite == SYS_CFGCTRL_WRITE) {
+    MmioWrite32(ARM_VE_SYS_CFGDATA_REG, *Data);
+  }
+
+  // Set the control value
+  SysCfgCtrl = SYS_CFGCTRL_START | ReadWrite | SYS_CFGCTRL_FUNCTION(Function) | SYS_CFGCTRL_SITE(Site) |
+      SYS_CFGCTRL_POSITION(Position) | SYS_CFGCTRL_DEVICE(Device);
+  MmioWrite32(ARM_VE_SYS_CFGCTRL_REG, SysCfgCtrl);
+
+  // Wait until the COMPLETE bit is set
+  while ((MmioRead32(ARM_VE_SYS_CFGSTAT_REG) & SYS_CFGSTAT_COMPLETE) == 0);
+
+  // Check for errors
+  if(MmioRead32(ARM_VE_SYS_CFGSTAT_REG) & SYS_CFGSTAT_ERROR) {
+    return RETURN_DEVICE_ERROR;
+  }
+
+  // If reading then get the data value
+  if(ReadWrite == SYS_CFGCTRL_READ) {
+    *Data = MmioRead32(ARM_VE_SYS_CFGDATA_REG);
+  }
+
+  return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+ArmPlatformSysConfigGet (
+  IN  SYS_CONFIG_FUNCTION   Function,
+  OUT UINT32*               Value
+  )
+{
+  UINT32          Site;
+  UINT32          Position;
+  UINT32          Device;
+
+  Position = 0;
+  Device = 0;
+
+  // Intercept some functions
+  switch(Function) {
+
+  case SYS_CFG_OSC_SITE1:
+    Function = SYS_CFG_OSC;
+    Site = ARM_VE_DAUGHTERBOARD_1_SITE;
+    break;
+
+  case SYS_CFG_OSC_SITE2:
+    Function = SYS_CFG_OSC;
+    Site = ARM_VE_DAUGHTERBOARD_2_SITE;
+    break;
+
+  case SYS_CFG_MUXFPGA:
+    Site = *Value;
+    break;
+
+  case SYS_CFG_OSC:
+  case SYS_CFG_VOLT:
+  case SYS_CFG_AMP:
+  case SYS_CFG_TEMP:
+  case SYS_CFG_RESET:
+  case SYS_CFG_SCC:
+  case SYS_CFG_DVIMODE:
+  case SYS_CFG_POWER:
+    Site = ARM_VE_MOTHERBOARD_SITE;
+    break;
+
+  case SYS_CFG_SHUTDOWN:
+  case SYS_CFG_REBOOT:
+  case SYS_CFG_RTC:
+  default:
+    return RETURN_UNSUPPORTED;
+  }
+
+  return AccessSysCfgRegister (SYS_CFGCTRL_READ, Function, Site, Position, Device, Value);
+}
+
+RETURN_STATUS
+ArmPlatformSysConfigGetValues (
+  IN  SYS_CONFIG_FUNCTION   Function,
+  IN  UINTN                 Size,
+  OUT UINT32*               Values
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
+
+RETURN_STATUS
+ArmPlatformSysConfigSet (
+  IN  SYS_CONFIG_FUNCTION   Function,
+  IN  UINT32                Value
+  )
+{
+  UINT32          Site;
+  UINT32          Position;
+  UINT32          Device;
+
+  Position = 0;
+  Device = 0;
+
+  // Intercept some functions
+  switch(Function) {
+
+  case SYS_CFG_OSC_SITE1:
+    Function = SYS_CFG_OSC;
+    Site = ARM_VE_DAUGHTERBOARD_1_SITE;
+    break;
+
+  case SYS_CFG_OSC_SITE2:
+    Function = SYS_CFG_OSC;
+    Site = ARM_VE_DAUGHTERBOARD_2_SITE;
+    break;
+
+  case SYS_CFG_MUXFPGA:
+    Site = Value;
+    break;
+
+  case SYS_CFG_RESET:
+  case SYS_CFG_SCC:
+  case SYS_CFG_SHUTDOWN:
+  case SYS_CFG_REBOOT:
+  case SYS_CFG_DVIMODE:
+  case SYS_CFG_POWER:
+    Site = ARM_VE_MOTHERBOARD_SITE;
+    break;
+
+  case SYS_CFG_OSC:
+  case SYS_CFG_VOLT:
+  case SYS_CFG_AMP:
+  case SYS_CFG_TEMP:
+  case SYS_CFG_RTC:
+  default:
+    return RETURN_UNSUPPORTED;
+  }
+
+  return AccessSysCfgRegister (SYS_CFGCTRL_WRITE, Function, Site, Position, Device, &Value);
+}
+
+RETURN_STATUS
+ArmPlatformSysConfigSetDevice (
+  IN  SYS_CONFIG_FUNCTION   Function,
+  IN  UINT32                Device,
+  IN  UINT32                Value
+  )
+{
+  UINT32          Site;
+  UINT32          Position;
+
+  Position = 0;
+
+  // Intercept some functions
+  switch(Function) {
+  case SYS_CFG_SCC:
+#ifdef ARM_VE_SCC_BASE
+    if (EfiAtRuntime ()) {
+      return RETURN_UNSUPPORTED;
+    }
+    MmioWrite32 ((ARM_VE_SCC_BASE + (Device * 4)),Value);
+    return RETURN_SUCCESS;
+#else
+    // There is no System Configuration Controller on the Model
+    return RETURN_UNSUPPORTED;
+#endif
+
+  case SYS_CFG_OSC_SITE1:
+    Function = SYS_CFG_OSC;
+    Site = ARM_VE_DAUGHTERBOARD_1_SITE;
+    break;
+
+  case SYS_CFG_OSC_SITE2:
+    Function = SYS_CFG_OSC;
+    Site = ARM_VE_DAUGHTERBOARD_2_SITE;
+    break;
+
+  case SYS_CFG_MUXFPGA:
+    Site = Value;
+    break;
+
+  case SYS_CFG_RTC:
+    return RETURN_UNSUPPORTED;
+    //break;
+
+  case SYS_CFG_OSC:
+  case SYS_CFG_VOLT:
+  case SYS_CFG_AMP:
+  case SYS_CFG_TEMP:
+  case SYS_CFG_RESET:
+  case SYS_CFG_SHUTDOWN:
+  case SYS_CFG_REBOOT:
+  case SYS_CFG_DVIMODE:
+  case SYS_CFG_POWER:
+    Site = ARM_VE_MOTHERBOARD_SITE;
+    break;
+  default:
+    return RETURN_UNSUPPORTED;
+  }
+
+  return AccessSysCfgRegister (SYS_CFGCTRL_WRITE, Function, Site, Position, Device, &Value);
+}
diff --git a/Platform/ARM/VExpressPkg/Library/ArmVExpressSysConfigRuntimeLib/ArmVExpressSysConfigRuntimeLib.inf b/Platform/ARM/VExpressPkg/Library/ArmVExpressSysConfigRuntimeLib/ArmVExpressSysConfigRuntimeLib.inf
new file mode 100644
index 000000000000..cce8b9096f6d
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Library/ArmVExpressSysConfigRuntimeLib/ArmVExpressSysConfigRuntimeLib.inf
@@ -0,0 +1,37 @@ 
+#/** @file
+#
+#  Component description file for ArmVExpressSysConfigRuntimeLib module
+#
+#  Copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR>
+#  Copyright (c) 2015, Linaro 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                      = ArmVExpressSysConfigRuntimeLib
+  FILE_GUID                      = 6275b819-615c-4a36-814a-c1f330b4e5d9
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = ArmPlatformSysConfigLib|DXE_RUNTIME_DRIVER
+
+[Sources.common]
+  ArmVExpressSysConfigRuntimeLib.c
+
+[Packages]
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  MdePkg/MdePkg.dec
+  Platform/ARM/VExpressPkg/ArmVExpressPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  IoLib
+  UefiRuntimeLib
diff --git a/Platform/ARM/VExpressPkg/Library/HdLcdArmVExpressLib/HdLcdArmVExpress.c b/Platform/ARM/VExpressPkg/Library/HdLcdArmVExpressLib/HdLcdArmVExpress.c
new file mode 100644
index 000000000000..b1106ee19b98
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Library/HdLcdArmVExpressLib/HdLcdArmVExpress.c
@@ -0,0 +1,285 @@ 
+/**
+
+  Copyright (c) 2012, ARM Ltd. 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 <PiDxe.h>
+
+#include <Library/ArmPlatformSysConfigLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/LcdPlatformLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/EdidDiscovered.h>
+#include <Protocol/EdidActive.h>
+
+#include <ArmPlatform.h>
+
+typedef struct {
+  UINT32                     Mode;
+  UINT32                     HorizontalResolution;
+  UINT32                     VerticalResolution;
+  LCD_BPP                    Bpp;
+  UINT32                     OscFreq;
+
+  // These are used by HDLCD
+  UINT32                     HSync;
+  UINT32                     HBackPorch;
+  UINT32                     HFrontPorch;
+  UINT32                     VSync;
+  UINT32                     VBackPorch;
+  UINT32                     VFrontPorch;
+} LCD_RESOLUTION;
+
+
+LCD_RESOLUTION mResolutions[] = {
+  { // Mode 0 : VGA : 640 x 480 x 24 bpp
+    VGA, VGA_H_RES_PIXELS, VGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, VGA_OSC_FREQUENCY,
+    VGA_H_SYNC, VGA_H_BACK_PORCH, VGA_H_FRONT_PORCH,
+    VGA_V_SYNC, VGA_V_BACK_PORCH, VGA_V_FRONT_PORCH
+  },
+  { // Mode 1 : SVGA : 800 x 600 x 24 bpp
+    SVGA, SVGA_H_RES_PIXELS, SVGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, SVGA_OSC_FREQUENCY,
+    SVGA_H_SYNC, SVGA_H_BACK_PORCH, SVGA_H_FRONT_PORCH,
+    SVGA_V_SYNC, SVGA_V_BACK_PORCH, SVGA_V_FRONT_PORCH
+  },
+  { // Mode 2 : XGA : 1024 x 768 x 24 bpp
+    XGA, XGA_H_RES_PIXELS, XGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, XGA_OSC_FREQUENCY,
+    XGA_H_SYNC, XGA_H_BACK_PORCH, XGA_H_FRONT_PORCH,
+    XGA_V_SYNC, XGA_V_BACK_PORCH, XGA_V_FRONT_PORCH
+  },
+  { // Mode 3 : SXGA : 1280 x 1024 x 24 bpp
+    SXGA, SXGA_H_RES_PIXELS, SXGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, (SXGA_OSC_FREQUENCY/2),
+    SXGA_H_SYNC, SXGA_H_BACK_PORCH, SXGA_H_FRONT_PORCH,
+    SXGA_V_SYNC, SXGA_V_BACK_PORCH, SXGA_V_FRONT_PORCH
+  },
+  { // Mode 4 : UXGA : 1600 x 1200 x 24 bpp
+    UXGA, UXGA_H_RES_PIXELS, UXGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, (UXGA_OSC_FREQUENCY/2),
+    UXGA_H_SYNC, UXGA_H_BACK_PORCH, UXGA_H_FRONT_PORCH,
+    UXGA_V_SYNC, UXGA_V_BACK_PORCH, UXGA_V_FRONT_PORCH
+  },
+  { // Mode 5 : HD : 1920 x 1080 x 24 bpp
+    HD, HD_H_RES_PIXELS, HD_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, (HD_OSC_FREQUENCY/2),
+    HD_H_SYNC, HD_H_BACK_PORCH, HD_H_FRONT_PORCH,
+    HD_V_SYNC, HD_V_BACK_PORCH, HD_V_FRONT_PORCH
+  }
+};
+
+EFI_EDID_DISCOVERED_PROTOCOL  mEdidDiscovered = {
+  0,
+  NULL
+};
+
+EFI_EDID_ACTIVE_PROTOCOL      mEdidActive = {
+  0,
+  NULL
+};
+
+EFI_STATUS
+LcdPlatformInitializeDisplay (
+  IN EFI_HANDLE   Handle
+  )
+{
+  EFI_STATUS  Status;
+
+  // Set the FPGA multiplexer to select the video output from the motherboard or the daughterboard
+  Status = ArmPlatformSysConfigSet (SYS_CFG_MUXFPGA, ARM_VE_DAUGHTERBOARD_1_SITE);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  // Install the EDID Protocols
+  Status = gBS->InstallMultipleProtocolInterfaces (
+    &Handle,
+    &gEfiEdidDiscoveredProtocolGuid,  &mEdidDiscovered,
+    &gEfiEdidActiveProtocolGuid,      &mEdidActive,
+    NULL
+  );
+
+  return Status;
+}
+
+EFI_STATUS
+LcdPlatformGetVram (
+  OUT EFI_PHYSICAL_ADDRESS*  VramBaseAddress,
+  OUT UINTN*                 VramSize
+  )
+{
+  EFI_STATUS              Status;
+  EFI_ALLOCATE_TYPE       AllocationType;
+
+  // Set the vram size
+  *VramSize = LCD_VRAM_SIZE;
+
+  *VramBaseAddress = (EFI_PHYSICAL_ADDRESS)LCD_VRAM_CORE_TILE_BASE;
+
+  // Allocate the VRAM from the DRAM so that nobody else uses it.
+  if (*VramBaseAddress == 0) {
+    AllocationType = AllocateAnyPages;
+  } else {
+    AllocationType = AllocateAddress;
+  }
+  Status = gBS->AllocatePages (AllocationType, EfiBootServicesData, EFI_SIZE_TO_PAGES(((UINTN)LCD_VRAM_SIZE)), VramBaseAddress);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  // Mark the VRAM as write-combining. The VRAM is inside the DRAM, which is cacheable.
+  Status = gDS->SetMemorySpaceAttributes (*VramBaseAddress, *VramSize,
+                  EFI_MEMORY_WC);
+  ASSERT_EFI_ERROR(Status);
+  if (EFI_ERROR(Status)) {
+    gBS->FreePages (*VramBaseAddress, EFI_SIZE_TO_PAGES (*VramSize));
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+UINT32
+LcdPlatformGetMaxMode (
+  VOID
+  )
+{
+  //
+  // The following line will report correctly the total number of graphics modes
+  // that could be supported by the graphics driver:
+  //
+  return (sizeof(mResolutions) / sizeof(LCD_RESOLUTION));
+}
+
+EFI_STATUS
+LcdPlatformSetMode (
+  IN UINT32                         ModeNumber
+  )
+{
+  EFI_STATUS            Status;
+
+  if (ModeNumber >= LcdPlatformGetMaxMode ()) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Set the video mode oscillator
+  do {
+    Status = ArmPlatformSysConfigSetDevice (SYS_CFG_OSC_SITE1, PcdGet32(PcdHdLcdVideoModeOscId), mResolutions[ModeNumber].OscFreq);
+  } while (Status == EFI_TIMEOUT);
+  if (EFI_ERROR(Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+  // Set the DVI into the new mode
+  do {
+    Status = ArmPlatformSysConfigSet (SYS_CFG_DVIMODE, mResolutions[ModeNumber].Mode);
+  } while (Status == EFI_TIMEOUT);
+  if (EFI_ERROR(Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+  // Set the multiplexer
+  Status = ArmPlatformSysConfigSet (SYS_CFG_MUXFPGA, ARM_VE_DAUGHTERBOARD_1_SITE);
+  if (EFI_ERROR(Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+  return Status;
+}
+
+EFI_STATUS
+LcdPlatformQueryMode (
+  IN  UINT32                                ModeNumber,
+  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info
+  )
+{
+  if (ModeNumber >= LcdPlatformGetMaxMode ()) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Info->Version = 0;
+  Info->HorizontalResolution = mResolutions[ModeNumber].HorizontalResolution;
+  Info->VerticalResolution = mResolutions[ModeNumber].VerticalResolution;
+  Info->PixelsPerScanLine = mResolutions[ModeNumber].HorizontalResolution;
+
+  switch (mResolutions[ModeNumber].Bpp) {
+    case LCD_BITS_PER_PIXEL_24:
+      Info->PixelFormat                   = PixelRedGreenBlueReserved8BitPerColor;
+      Info->PixelInformation.RedMask      = LCD_24BPP_RED_MASK;
+      Info->PixelInformation.GreenMask    = LCD_24BPP_GREEN_MASK;
+      Info->PixelInformation.BlueMask     = LCD_24BPP_BLUE_MASK;
+      Info->PixelInformation.ReservedMask = LCD_24BPP_RESERVED_MASK;
+      break;
+
+    case LCD_BITS_PER_PIXEL_16_555:
+    case LCD_BITS_PER_PIXEL_16_565:
+    case LCD_BITS_PER_PIXEL_12_444:
+    case LCD_BITS_PER_PIXEL_8:
+    case LCD_BITS_PER_PIXEL_4:
+    case LCD_BITS_PER_PIXEL_2:
+    case LCD_BITS_PER_PIXEL_1:
+    default:
+      // These are not supported
+      ASSERT(FALSE);
+      break;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+LcdPlatformGetTimings (
+  IN  UINT32                              ModeNumber,
+  OUT UINT32*                             HRes,
+  OUT UINT32*                             HSync,
+  OUT UINT32*                             HBackPorch,
+  OUT UINT32*                             HFrontPorch,
+  OUT UINT32*                             VRes,
+  OUT UINT32*                             VSync,
+  OUT UINT32*                             VBackPorch,
+  OUT UINT32*                             VFrontPorch
+  )
+{
+  if (ModeNumber >= LcdPlatformGetMaxMode ()) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *HRes           = mResolutions[ModeNumber].HorizontalResolution;
+  *HSync          = mResolutions[ModeNumber].HSync;
+  *HBackPorch     = mResolutions[ModeNumber].HBackPorch;
+  *HFrontPorch    = mResolutions[ModeNumber].HFrontPorch;
+  *VRes           = mResolutions[ModeNumber].VerticalResolution;
+  *VSync          = mResolutions[ModeNumber].VSync;
+  *VBackPorch     = mResolutions[ModeNumber].VBackPorch;
+  *VFrontPorch    = mResolutions[ModeNumber].VFrontPorch;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+LcdPlatformGetBpp (
+  IN  UINT32                              ModeNumber,
+  OUT LCD_BPP  *                          Bpp
+  )
+{
+  if (ModeNumber >= LcdPlatformGetMaxMode ()) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Bpp = mResolutions[ModeNumber].Bpp;
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/ARM/VExpressPkg/Library/HdLcdArmVExpressLib/HdLcdArmVExpressLib.inf b/Platform/ARM/VExpressPkg/Library/HdLcdArmVExpressLib/HdLcdArmVExpressLib.inf
new file mode 100644
index 000000000000..fc51c781b451
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Library/HdLcdArmVExpressLib/HdLcdArmVExpressLib.inf
@@ -0,0 +1,45 @@ 
+#/** @file
+#
+#  Component description file for HdLcdArmLib module
+#
+#  Copyright (c) 2011-2012, 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                      = HdLcdArmVExpress
+  FILE_GUID                      = 535a720e-06c0-4bb9-b563-452216abbed4
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = LcdPlatformLib
+
+[Sources.common]
+
+HdLcdArmVExpress.c
+
+[Packages]
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  MdePkg/MdePkg.dec
+  Platform/ARM/VExpressPkg/ArmVExpressPkg.dec
+
+[LibraryClasses]
+  ArmPlatformSysConfigLib
+  BaseLib
+  DxeServicesTableLib
+
+[Protocols]
+  gEfiEdidDiscoveredProtocolGuid                # Produced
+  gEfiEdidActiveProtocolGuid                    # Produced
+
+[Pcd]
+  gArmVExpressTokenSpaceGuid.PcdPL111LcdMaxMode
+  gArmVExpressTokenSpaceGuid.PcdHdLcdVideoModeOscId
diff --git a/Platform/ARM/VExpressPkg/Library/NorFlashArmVExpressLib/NorFlashArmVExpress.c b/Platform/ARM/VExpressPkg/Library/NorFlashArmVExpressLib/NorFlashArmVExpress.c
new file mode 100644
index 000000000000..a136bff4a1d6
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Library/NorFlashArmVExpressLib/NorFlashArmVExpress.c
@@ -0,0 +1,84 @@ 
+/** @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>
+
+#define NOR_FLASH_DEVICE_COUNT                     4
+
+NOR_FLASH_DESCRIPTION mNorFlashDevices[NOR_FLASH_DEVICE_COUNT] = {
+  { // BootMon
+    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 } }
+  },
+  { // BootMon non-volatile storage
+    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 } }
+  },
+  { // UEFI
+    ARM_VE_SMB_NOR1_BASE,
+    ARM_VE_SMB_NOR1_BASE,
+    SIZE_256KB * 255,
+    SIZE_256KB,
+    { 0x1F15DA3C, 0x37FF, 0x4070, { 0xB4, 0x71, 0xBB, 0x4A, 0xF1, 0x2A, 0x72, 0x4A } }
+  },
+  { // UEFI Variable Services non-volatile storage
+    ARM_VE_SMB_NOR1_BASE,
+    ARM_VE_SMB_NOR1_BASE + SIZE_256KB * 255,
+    SIZE_64KB * 3, //FIXME: Set 3 blocks because I did not succeed to copy 4 blocks into the ARM Versatile Express NOR Flash in the last NOR Flash. It should be 4 blocks
+    SIZE_64KB,
+    { 0xCC2CBF29, 0x1498, 0x4CDD, { 0x81, 0x71, 0xF8, 0xB6, 0xB4, 0x1D, 0x09, 0x09 } }
+  }
+};
+
+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, "NorFlashWriteBlocks: 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 = NOR_FLASH_DEVICE_COUNT;
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/ARM/VExpressPkg/Library/NorFlashArmVExpressLib/NorFlashArmVExpressLib.inf b/Platform/ARM/VExpressPkg/Library/NorFlashArmVExpressLib/NorFlashArmVExpressLib.inf
new file mode 100644
index 000000000000..6c0ca97c9900
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Library/NorFlashArmVExpressLib/NorFlashArmVExpressLib.inf
@@ -0,0 +1,33 @@ 
+#/** @file
+#
+#  Copyright (c) 2011, 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                      = NorFlashArmVExpressLib
+  FILE_GUID                      = c0f5dfa0-7599-11e0-9665-0002a5d5c51b
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = NorFlashPlatformLib
+
+[Sources.common]
+  NorFlashArmVExpress.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  Platform/ARM/VExpressPkg/ArmVExpressPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  IoLib
diff --git a/Platform/ARM/VExpressPkg/Library/PL111LcdArmVExpressLib/PL111LcdArmVExpress.c b/Platform/ARM/VExpressPkg/Library/PL111LcdArmVExpressLib/PL111LcdArmVExpress.c
new file mode 100644
index 000000000000..3f3ceb3d2fa8
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Library/PL111LcdArmVExpressLib/PL111LcdArmVExpress.c
@@ -0,0 +1,370 @@ 
+/** @file
+
+  Copyright (c) 2011-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 <PiDxe.h>
+
+#include <Library/ArmPlatformSysConfigLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/LcdPlatformLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/EdidDiscovered.h>
+#include <Protocol/EdidActive.h>
+
+#include <ArmPlatform.h>
+
+typedef struct {
+  UINT32                     Mode;
+  UINT32                     HorizontalResolution;
+  UINT32                     VerticalResolution;
+  LCD_BPP                    Bpp;
+  UINT32                     OscFreq;
+
+  UINT32                     HSync;
+  UINT32                     HBackPorch;
+  UINT32                     HFrontPorch;
+  UINT32                     VSync;
+  UINT32                     VBackPorch;
+  UINT32                     VFrontPorch;
+} LCD_RESOLUTION;
+
+
+LCD_RESOLUTION mResolutions[] = {
+  { // Mode 0 : VGA : 640 x 480 x 24 bpp
+      VGA, VGA_H_RES_PIXELS, VGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, VGA_OSC_FREQUENCY,
+      VGA_H_SYNC, VGA_H_BACK_PORCH, VGA_H_FRONT_PORCH,
+      VGA_V_SYNC, VGA_V_BACK_PORCH, VGA_V_FRONT_PORCH
+  },
+  { // Mode 1 : SVGA : 800 x 600 x 24 bpp
+      SVGA, SVGA_H_RES_PIXELS, SVGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, SVGA_OSC_FREQUENCY,
+      SVGA_H_SYNC, SVGA_H_BACK_PORCH, SVGA_H_FRONT_PORCH,
+      SVGA_V_SYNC, SVGA_V_BACK_PORCH, SVGA_V_FRONT_PORCH
+  },
+  { // Mode 2 : XGA : 1024 x 768 x 24 bpp
+      XGA, XGA_H_RES_PIXELS, XGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, XGA_OSC_FREQUENCY,
+      XGA_H_SYNC, XGA_H_BACK_PORCH, XGA_H_FRONT_PORCH,
+      XGA_V_SYNC, XGA_V_BACK_PORCH, XGA_V_FRONT_PORCH
+  },
+  { // Mode 3 : SXGA : 1280 x 1024 x 24 bpp
+      SXGA, SXGA_H_RES_PIXELS, SXGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, (SXGA_OSC_FREQUENCY/2),
+      SXGA_H_SYNC, SXGA_H_BACK_PORCH, SXGA_H_FRONT_PORCH,
+      SXGA_V_SYNC, SXGA_V_BACK_PORCH, SXGA_V_FRONT_PORCH
+  },
+  { // Mode 4 : UXGA : 1600 x 1200 x 24 bpp
+      UXGA, UXGA_H_RES_PIXELS, UXGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, (UXGA_OSC_FREQUENCY/2),
+      UXGA_H_SYNC, UXGA_H_BACK_PORCH, UXGA_H_FRONT_PORCH,
+      UXGA_V_SYNC, UXGA_V_BACK_PORCH, UXGA_V_FRONT_PORCH
+  },
+  { // Mode 5 : HD : 1920 x 1080 x 24 bpp
+      HD, HD_H_RES_PIXELS, HD_V_RES_PIXELS, LCD_BITS_PER_PIXEL_24, (HD_OSC_FREQUENCY/2),
+      HD_H_SYNC, HD_H_BACK_PORCH, HD_H_FRONT_PORCH,
+      HD_V_SYNC, HD_V_BACK_PORCH, HD_V_FRONT_PORCH
+  },
+  { // Mode 6 : VGA : 640 x 480 x 16 bpp (565 Mode)
+      VGA, VGA_H_RES_PIXELS, VGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_16_565, VGA_OSC_FREQUENCY,
+      VGA_H_SYNC, VGA_H_BACK_PORCH, VGA_H_FRONT_PORCH,
+      VGA_V_SYNC, VGA_V_BACK_PORCH, VGA_V_FRONT_PORCH
+  },
+  { // Mode 7 : SVGA : 800 x 600 x 16 bpp (565 Mode)
+      SVGA, SVGA_H_RES_PIXELS, SVGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_16_565, SVGA_OSC_FREQUENCY,
+      SVGA_H_SYNC, SVGA_H_BACK_PORCH, SVGA_H_FRONT_PORCH,
+      SVGA_V_SYNC, SVGA_V_BACK_PORCH, SVGA_V_FRONT_PORCH
+  },
+  { // Mode 8 : XGA : 1024 x 768 x 16 bpp (565 Mode)
+      XGA, XGA_H_RES_PIXELS, XGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_16_565, XGA_OSC_FREQUENCY,
+      XGA_H_SYNC, XGA_H_BACK_PORCH, XGA_H_FRONT_PORCH,
+      XGA_V_SYNC, XGA_V_BACK_PORCH, XGA_V_FRONT_PORCH
+  },
+  { // Mode 9 : VGA : 640 x 480 x 15 bpp
+      VGA, VGA_H_RES_PIXELS, VGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_16_555, VGA_OSC_FREQUENCY,
+      VGA_H_SYNC, VGA_H_BACK_PORCH, VGA_H_FRONT_PORCH,
+      VGA_V_SYNC, VGA_V_BACK_PORCH, VGA_V_FRONT_PORCH
+  },
+  { // Mode 10 : SVGA : 800 x 600 x 15 bpp
+      SVGA, SVGA_H_RES_PIXELS, SVGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_16_555, SVGA_OSC_FREQUENCY,
+      SVGA_H_SYNC, SVGA_H_BACK_PORCH, SVGA_H_FRONT_PORCH,
+      SVGA_V_SYNC, SVGA_V_BACK_PORCH, SVGA_V_FRONT_PORCH
+  },
+  { // Mode 11 : XGA : 1024 x 768 x 15 bpp
+      XGA, XGA_H_RES_PIXELS, XGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_16_555, XGA_OSC_FREQUENCY,
+      XGA_H_SYNC, XGA_H_BACK_PORCH, XGA_H_FRONT_PORCH,
+      XGA_V_SYNC, XGA_V_BACK_PORCH, XGA_V_FRONT_PORCH
+  },
+  { // Mode 12 : XGA : 1024 x 768 x 15 bpp - All the timing info is derived from Linux Kernel Driver Settings
+      XGA, XGA_H_RES_PIXELS, XGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_16_555, 63500000,
+      XGA_H_SYNC, XGA_H_BACK_PORCH, XGA_H_FRONT_PORCH,
+      XGA_V_SYNC, XGA_V_BACK_PORCH, XGA_V_FRONT_PORCH
+  },
+  { // Mode 13 : VGA : 640 x 480 x 12 bpp (444 Mode)
+      VGA, VGA_H_RES_PIXELS, VGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_12_444, VGA_OSC_FREQUENCY,
+      VGA_H_SYNC, VGA_H_BACK_PORCH, VGA_H_FRONT_PORCH,
+      VGA_V_SYNC, VGA_V_BACK_PORCH, VGA_V_FRONT_PORCH
+  },
+  { // Mode 14 : SVGA : 800 x 600 x 12 bpp (444 Mode)
+      SVGA, SVGA_H_RES_PIXELS, SVGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_12_444, SVGA_OSC_FREQUENCY,
+      SVGA_H_SYNC, SVGA_H_BACK_PORCH, SVGA_H_FRONT_PORCH,
+      SVGA_V_SYNC, SVGA_V_BACK_PORCH, SVGA_V_FRONT_PORCH
+  },
+  { // Mode 15 : XGA : 1024 x 768 x 12 bpp (444 Mode)
+      XGA, XGA_H_RES_PIXELS, XGA_V_RES_PIXELS, LCD_BITS_PER_PIXEL_12_444, XGA_OSC_FREQUENCY,
+      XGA_H_SYNC, XGA_H_BACK_PORCH, XGA_H_FRONT_PORCH,
+      XGA_V_SYNC, XGA_V_BACK_PORCH, XGA_V_FRONT_PORCH
+  }
+};
+
+EFI_EDID_DISCOVERED_PROTOCOL  mEdidDiscovered = {
+  0,
+  NULL
+};
+
+EFI_EDID_ACTIVE_PROTOCOL      mEdidActive = {
+  0,
+  NULL
+};
+
+
+EFI_STATUS
+LcdPlatformInitializeDisplay (
+  IN EFI_HANDLE   Handle
+  )
+{
+  EFI_STATUS  Status;
+
+  // Set the FPGA multiplexer to select the video output from the motherboard or the daughterboard
+  Status = ArmPlatformSysConfigSet (SYS_CFG_MUXFPGA, PL111_CLCD_SITE);
+  if (!EFI_ERROR(Status)) {
+    // Install the EDID Protocols
+    Status = gBS->InstallMultipleProtocolInterfaces(
+      &Handle,
+      &gEfiEdidDiscoveredProtocolGuid,  &mEdidDiscovered,
+      &gEfiEdidActiveProtocolGuid,      &mEdidActive,
+      NULL
+    );
+  }
+
+  return Status;
+}
+
+EFI_STATUS
+LcdPlatformGetVram (
+  OUT EFI_PHYSICAL_ADDRESS*  VramBaseAddress,
+  OUT UINTN*                 VramSize
+  )
+{
+  EFI_STATUS              Status;
+
+  Status = EFI_SUCCESS;
+
+  // Is it on the motherboard or on the daughterboard?
+  switch(PL111_CLCD_SITE) {
+
+  case ARM_VE_MOTHERBOARD_SITE:
+    *VramBaseAddress = (EFI_PHYSICAL_ADDRESS) PL111_CLCD_VRAM_MOTHERBOARD_BASE;
+    *VramSize = LCD_VRAM_SIZE;
+    break;
+
+  case ARM_VE_DAUGHTERBOARD_1_SITE:
+    *VramBaseAddress = (EFI_PHYSICAL_ADDRESS) LCD_VRAM_CORE_TILE_BASE;
+    *VramSize = LCD_VRAM_SIZE;
+
+    // Allocate the VRAM from the DRAM so that nobody else uses it.
+    Status = gBS->AllocatePages( AllocateAddress, EfiBootServicesData, EFI_SIZE_TO_PAGES(((UINTN)LCD_VRAM_SIZE)), VramBaseAddress);
+    if (EFI_ERROR(Status)) {
+      return Status;
+    }
+
+    // Mark the VRAM as write-combining. The VRAM is inside the DRAM, which is cacheable.
+    Status = gDS->SetMemorySpaceAttributes (*VramBaseAddress, *VramSize,
+                    EFI_MEMORY_WC);
+    ASSERT_EFI_ERROR(Status);
+    if (EFI_ERROR(Status)) {
+      gBS->FreePages (*VramBaseAddress, EFI_SIZE_TO_PAGES(*VramSize));
+      return Status;
+    }
+    break;
+
+  default:
+    // Unsupported site
+    Status = EFI_UNSUPPORTED;
+    break;
+  }
+
+  return Status;
+}
+
+UINT32
+LcdPlatformGetMaxMode (
+  VOID
+  )
+{
+  // The following line will report correctly the total number of graphics modes
+  // supported by the PL111CLCD.
+  //return (sizeof(mResolutions) / sizeof(CLCD_RESOLUTION)) - 1;
+
+  // However, on some platforms it is desirable to ignore some graphics modes.
+  // This could be because the specific implementation of PL111 has certain limitations.
+
+  // Set the maximum mode allowed
+  return (PcdGet32(PcdPL111LcdMaxMode));
+}
+
+EFI_STATUS
+LcdPlatformSetMode (
+  IN UINT32                         ModeNumber
+  )
+{
+  EFI_STATUS            Status;
+  UINT32                LcdSite;
+  UINT32                OscillatorId;
+  SYS_CONFIG_FUNCTION   Function;
+  UINT32                SysId;
+
+  if (ModeNumber >= LcdPlatformGetMaxMode ()) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  LcdSite = PL111_CLCD_SITE;
+
+  switch(LcdSite) {
+  case ARM_VE_MOTHERBOARD_SITE:
+    Function = SYS_CFG_OSC;
+    OscillatorId = PL111_CLCD_MOTHERBOARD_VIDEO_MODE_OSC_ID;
+    break;
+  case ARM_VE_DAUGHTERBOARD_1_SITE:
+    Function = SYS_CFG_OSC_SITE1;
+    OscillatorId = (UINT32)PcdGet32(PcdPL111LcdVideoModeOscId);
+    break;
+  default:
+    return EFI_UNSUPPORTED;
+  }
+
+  // Set the video mode oscillator
+  Status = ArmPlatformSysConfigSetDevice (Function, OscillatorId, mResolutions[ModeNumber].OscFreq);
+  if (EFI_ERROR(Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+  // The FVP foundation model does not have an LCD.
+  // On the FVP models the GIC variant in encoded in bits [15:12].
+  // Note: The DVI Mode is not modelled by RTSM or FVP models.
+  SysId = MmioRead32 (ARM_VE_SYS_ID_REG);
+  if (SysId != ARM_RTSM_SYS_ID) {
+    // Take out the FVP GIC variant to reduce the permutations.
+    SysId &= ~ARM_FVP_SYS_ID_VARIANT_MASK;
+    if (SysId != ARM_FVP_BASE_BOARD_SYS_ID) {
+      // Set the DVI into the new mode
+      Status = ArmPlatformSysConfigSet (SYS_CFG_DVIMODE, mResolutions[ModeNumber].Mode);
+      if (EFI_ERROR(Status)) {
+        ASSERT_EFI_ERROR (Status);
+        return Status;
+      }
+    }
+  }
+
+  // Set the multiplexer
+  Status = ArmPlatformSysConfigSet (SYS_CFG_MUXFPGA, LcdSite);
+  if (EFI_ERROR(Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
+
+  return Status;
+}
+
+EFI_STATUS
+LcdPlatformQueryMode (
+  IN  UINT32                                ModeNumber,
+  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info
+  )
+{
+  if (ModeNumber >= LcdPlatformGetMaxMode ()) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Info->Version = 0;
+  Info->HorizontalResolution = mResolutions[ModeNumber].HorizontalResolution;
+  Info->VerticalResolution = mResolutions[ModeNumber].VerticalResolution;
+  Info->PixelsPerScanLine = mResolutions[ModeNumber].HorizontalResolution;
+
+  switch (mResolutions[ModeNumber].Bpp) {
+    case LCD_BITS_PER_PIXEL_24:
+      Info->PixelFormat                   = PixelRedGreenBlueReserved8BitPerColor;
+      Info->PixelInformation.RedMask      = LCD_24BPP_RED_MASK;
+      Info->PixelInformation.GreenMask    = LCD_24BPP_GREEN_MASK;
+      Info->PixelInformation.BlueMask     = LCD_24BPP_BLUE_MASK;
+      Info->PixelInformation.ReservedMask = LCD_24BPP_RESERVED_MASK;
+      break;
+
+    case LCD_BITS_PER_PIXEL_16_555:
+    case LCD_BITS_PER_PIXEL_16_565:
+    case LCD_BITS_PER_PIXEL_12_444:
+    case LCD_BITS_PER_PIXEL_8:
+    case LCD_BITS_PER_PIXEL_4:
+    case LCD_BITS_PER_PIXEL_2:
+    case LCD_BITS_PER_PIXEL_1:
+    default:
+      // These are not supported
+      ASSERT(FALSE);
+      break;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+LcdPlatformGetTimings (
+  IN  UINT32                              ModeNumber,
+  OUT UINT32*                             HRes,
+  OUT UINT32*                             HSync,
+  OUT UINT32*                             HBackPorch,
+  OUT UINT32*                             HFrontPorch,
+  OUT UINT32*                             VRes,
+  OUT UINT32*                             VSync,
+  OUT UINT32*                             VBackPorch,
+  OUT UINT32*                             VFrontPorch
+  )
+{
+  if (ModeNumber >= LcdPlatformGetMaxMode ()) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *HRes           = mResolutions[ModeNumber].HorizontalResolution;
+  *HSync          = mResolutions[ModeNumber].HSync;
+  *HBackPorch     = mResolutions[ModeNumber].HBackPorch;
+  *HFrontPorch    = mResolutions[ModeNumber].HFrontPorch;
+  *VRes           = mResolutions[ModeNumber].VerticalResolution;
+  *VSync          = mResolutions[ModeNumber].VSync;
+  *VBackPorch     = mResolutions[ModeNumber].VBackPorch;
+  *VFrontPorch    = mResolutions[ModeNumber].VFrontPorch;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+LcdPlatformGetBpp (
+  IN  UINT32                              ModeNumber,
+  OUT LCD_BPP  *                          Bpp
+  )
+{
+  if (ModeNumber >= LcdPlatformGetMaxMode ()) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Bpp = mResolutions[ModeNumber].Bpp;
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/ARM/VExpressPkg/Library/PL111LcdArmVExpressLib/PL111LcdArmVExpressLib.inf b/Platform/ARM/VExpressPkg/Library/PL111LcdArmVExpressLib/PL111LcdArmVExpressLib.inf
new file mode 100644
index 000000000000..658558ab1523
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Library/PL111LcdArmVExpressLib/PL111LcdArmVExpressLib.inf
@@ -0,0 +1,44 @@ 
+#/** @file
+#
+#  Component description file for ArmVeGraphicsDxe module
+#
+#  Copyright (c) 2011-2012, 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                      = PL111LcdArmVExpressLib
+  FILE_GUID                      = b7f06f20-496f-11e0-a8e8-0002a5d5c51b
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = LcdPlatformLib
+
+[Sources.common]
+  PL111LcdArmVExpress.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  ArmPlatformPkg/ArmVExpressPkg/ArmVExpressPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+  ArmPlatformSysConfigLib
+  BaseLib
+  DxeServicesTableLib
+
+[Protocols]
+  gEfiEdidDiscoveredProtocolGuid                # Produced
+  gEfiEdidActiveProtocolGuid                    # Produced
+
+[Pcd]
+  gArmVExpressTokenSpaceGuid.PcdPL111LcdMaxMode
+  gArmVExpressTokenSpaceGuid.PcdPL111LcdVideoModeOscId
diff --git a/Platform/ARM/VExpressPkg/Library/ResetSystemLib/ResetSystemLib.c b/Platform/ARM/VExpressPkg/Library/ResetSystemLib/ResetSystemLib.c
new file mode 100644
index 000000000000..d2bc4a88fa5a
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Library/ResetSystemLib/ResetSystemLib.c
@@ -0,0 +1,111 @@ 
+/** @file
+  Template library implementation to support ResetSystem Runtime call.
+
+  Fill in the templates with what ever makes you system reset.
+
+  Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+  Copyright (c) 2013, ARM Ltd. All rights reserved.<BR>
+  Copyright (c) 2017, Linaro 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 <Base.h>
+
+#include <Library/ArmPlatformSysConfigLib.h>
+#include <Library/DebugLib.h>
+#include <Library/ResetSystemLib.h>
+
+#include <ArmPlatform.h>
+
+/**
+  This function causes a system-wide reset (cold reset), in which
+  all circuitry within the system returns to its initial state. This type of
+  reset is asynchronous to system operation and operates without regard to
+  cycle boundaries.
+
+  If this function returns, it means that the system does not support cold
+  reset.
+**/
+VOID
+EFIAPI
+ResetCold (
+  VOID
+  )
+{
+  ArmPlatformSysConfigSet (SYS_CFG_REBOOT, 0);
+}
+
+/**
+  This function causes a system-wide initialization (warm reset), in which all
+  processors are set to their initial state. Pending cycles are not corrupted.
+
+  If this function returns, it means that the system does not support warm
+  reset.
+**/
+VOID
+EFIAPI
+ResetWarm (
+  VOID
+  )
+{
+  ResetCold ();
+}
+
+/**
+  This function causes the system to enter a power state equivalent
+  to the ACPI G2/S5 or G3 states.
+
+  If this function returns, it means that the system does not support shut down reset.
+**/
+VOID
+EFIAPI
+ResetShutdown (
+  VOID
+  )
+{
+  ArmPlatformSysConfigSet (SYS_CFG_SHUTDOWN, 0);
+}
+
+/**
+  This function causes the system to enter S3 and then wake up immediately.
+
+  If this function returns, it means that the system does not support S3
+  feature.
+**/
+VOID
+EFIAPI
+EnterS3WithImmediateWake (
+  VOID
+  )
+{
+  // not implemented
+}
+
+/**
+  This function causes a systemwide reset. The exact type of the reset is
+  defined by the EFI_GUID that follows the Null-terminated Unicode string passed
+  into ResetData. If the platform does not recognize the EFI_GUID in ResetData
+  the platform must pick a supported reset type to perform.The platform may
+  optionally log the parameters from any non-normal reset that occurs.
+
+  @param[in]  DataSize   The size, in bytes, of ResetData.
+  @param[in]  ResetData  The data buffer starts with a Null-terminated string,
+                         followed by the EFI_GUID.
+**/
+VOID
+EFIAPI
+ResetPlatformSpecific (
+  IN UINTN   DataSize,
+  IN VOID    *ResetData
+  )
+{
+  ResetCold ();
+}
diff --git a/Platform/ARM/VExpressPkg/Library/ResetSystemLib/ResetSystemLib.inf b/Platform/ARM/VExpressPkg/Library/ResetSystemLib/ResetSystemLib.inf
new file mode 100644
index 000000000000..e7caf04f7f74
--- /dev/null
+++ b/Platform/ARM/VExpressPkg/Library/ResetSystemLib/ResetSystemLib.inf
@@ -0,0 +1,36 @@ 
+#/** @file
+# Reset System lib to make it easy to port new platforms
+#
+# Copyright (c) 2008, Apple Inc. All rights reserved.<BR>
+# Copyright (c) 2017, Linaro 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                      = ArmVeResetSystemLib
+  FILE_GUID                      = 36885202-0854-4373-bfd2-95d229b44d44
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = ResetSystemLib
+
+[Sources.common]
+  ResetSystemLib.c
+
+[Packages]
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  Platform/ARM/VExpressPkg/ArmVExpressPkg.dec
+
+[LibraryClasses]
+  DebugLib
+  ArmPlatformSysConfigLib