diff mbox

[edk2,v4,12/29] ArmVirtualizationPkg: Xen/PV relocatable platformlib instance

Message ID 1423739961-5945-13-git-send-email-ard.biesheuvel@linaro.org
State New
Headers show

Commit Message

Ard Biesheuvel Feb. 12, 2015, 11:19 a.m. UTC
Add a ArmPlatformLib instance that can deal with the self relocation
and truly dynamic discovery of system RAM base and size.

Contributed-under: TianoCore Contribution Agreement 1.0
Acked-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Olivier Martin <olivier.martin@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/MemnodeParser.S          | 237 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/RelocatableVirtHelper.S  | 167 ++++++++++++++++++++++++++++++++++++++++++++++
 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/ArmXenRelocatablePlatformLib.inf |  59 +++++++++++++++++
 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/RelocatableVirt.c                |  71 ++++++++++++++++++++
 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/XenVirtMem.c                     |  83 +++++++++++++++++++++++
 5 files changed, 617 insertions(+)
diff mbox

Patch

diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/MemnodeParser.S b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/MemnodeParser.S
new file mode 100644
index 000000000000..f919b63710f0
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/MemnodeParser.S
@@ -0,0 +1,237 @@ 
+/*
+ * Copyright (c) 2014, Linaro 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.
+ */
+
+/*
+ * Theory of operation
+ * -------------------
+ *
+ * This code parses a Flattened Device Tree binary (DTB) to find the base of
+ * system RAM. It is written in assembly so that it can be executed before a
+ * stack has been set up.
+ *
+ * To find the base of system RAM, we have to traverse the FDT to find a memory
+ * node. In the context of this implementation, the first node that has a
+ * device_type property with the value 'memory' and a 'reg' property is
+ * acceptable, and the name of the node (memory[@xxx]) is ignored, as are any
+ * other nodes that match the above constraints.
+ *
+ * In pseudo code, this implementation does the following:
+ *
+ * for each node {
+ *	have_device_type = false
+ *	have_reg = false
+ *
+ *	for each property {
+ *		if property value == 'memory' {
+ *			if property name == 'device_type' {
+ *				have_device_type = true
+ *			}
+ *		} else {
+ *			if property name == 'reg' {
+ *				have_reg = true
+ *				membase = property value[0]
+ *				memsize = property value[1]
+ *			}
+ *		}
+ *	}
+ *	if have_device_type and have_reg {
+ *		return membase and memsize
+ *	}
+ * }
+ * return NOT_FOUND
+ */
+
+#define FDT_MAGIC		0xedfe0dd0
+
+#define FDT_BEGIN_NODE		0x1
+#define FDT_END_NODE		0x2
+#define FDT_PROP		0x3
+#define FDT_END			0x9
+
+	xMEMSIZE	.req	x0	// recorded system RAM size
+	xMEMBASE	.req	x1	// recorded system RAM base
+
+	xLR		.req	x8	// our preserved link register
+	xDTP		.req	x9	// pointer to traverse the DT structure
+	xSTRTAB		.req	x10	// pointer to the DTB string table
+	xMEMNODE	.req	x11	// bit field to record found properties
+
+#define HAVE_REG		0x1
+#define HAVE_DEVICE_TYPE	0x2
+
+	.text
+	.align	3
+_memory:
+	.asciz	"memory"
+_reg:
+	.asciz	"reg"
+_device_type:
+	.asciz	"device_type"
+
+	/*
+	 * Compare strings in x4 and x5, return in w7
+	 */
+	.align	3
+strcmp:
+	ldrb	w2, [x4], #1
+	ldrb	w3, [x5], #1
+	subs	w7, w2, w3
+	cbz	w2, 0f
+	cbz	w3, 0f
+	beq	strcmp
+0:	ret
+
+	.globl	find_memnode
+find_memnode:
+	// preserve link register
+	mov	xLR, x30
+	mov	xDTP, x0
+
+	/*
+	 * Check the DTB magic at offset 0
+	 */
+	movz	w4, #:abs_g0_nc:FDT_MAGIC
+	movk	w4, #:abs_g1:FDT_MAGIC
+	ldr	w5, [xDTP]
+	cmp	w4, w5
+	bne	err_invalid_magic
+
+	/*
+	 * Read the string offset and store it for later use
+	 */
+	ldr	w4, [xDTP, #12]
+	rev	w4, w4
+	add	xSTRTAB, xDTP, x4
+
+	/*
+	 * Read the struct offset and add it to the DT pointer
+	 */
+	ldr	w5, [xDTP, #8]
+	rev	w5, w5
+	add	xDTP, xDTP, x5
+
+	/*
+	 * Check current tag for FDT_BEGIN_NODE
+	 */
+	ldr	w5, [xDTP]
+	rev	w5, w5
+	cmp	w5, #FDT_BEGIN_NODE
+	bne	err_unexpected_begin_tag
+
+begin_node:
+	mov	xMEMNODE, #0
+	add	xDTP, xDTP, #4
+
+	/*
+	 * Advance xDTP past NULL terminated string
+	 */
+0:	ldrb	w4, [xDTP], #1
+	cbnz	w4, 0b
+
+next_tag:
+	/*
+	 * Align the DT pointer xDTP to the next 32-bit boundary
+	 */
+	add	xDTP, xDTP, #3
+	and	xDTP, xDTP, #~3
+
+	/*
+	 * Read the next tag, could be BEGIN_NODE, END_NODE, PROP, END
+	 */
+	ldr	w5, [xDTP]
+	rev	w5, w5
+	cmp	w5, #FDT_BEGIN_NODE
+	beq	begin_node
+	cmp	w5, #FDT_END_NODE
+	beq	end_node
+	cmp	w5, #FDT_PROP
+	beq	prop_node
+	cmp	w5, #FDT_END
+	beq	err_end_of_fdt
+	b	err_unexpected_tag
+
+prop_node:
+	/*
+	 * If propname == 'reg', record as membase and memsize
+	 * If propname == 'device_type' and value == 'memory',
+	 * set the 'is_memnode' flag for this node
+	 */
+	ldr	w6, [xDTP, #4]
+	add	xDTP, xDTP, #12
+	rev	w6, w6
+	mov	x5, xDTP
+	adr	x4, _memory
+	bl	strcmp
+
+	/*
+	 * Get handle to property name
+	 */
+	ldr	w5, [xDTP, #-4]
+	rev	w5, w5
+	add	x5, xSTRTAB, x5
+
+	cbz	w7, check_device_type
+
+	/*
+	 * Check for 'reg' property
+	 */
+	adr	x4, _reg
+	bl	strcmp
+	cbnz	w7, inc_and_next_tag
+
+	/*
+	 * Extract two 64-bit quantities from the 'reg' property. These values
+	 * will only be used if the node also turns out to have a device_type
+	 * property with a value of 'memory'.
+	 *
+	 * NOTE: xDTP is only guaranteed to be 32 bit aligned, and we are most
+	 *       likely executing with the MMU off, so we cannot use 64 bit
+	 *       wide accesses here.
+	 */
+	ldp	w4, w5, [xDTP]
+	orr	xMEMBASE, x4, x5, lsl #32
+	ldp	w4, w5, [xDTP, #8]
+	orr	xMEMSIZE, x4, x5, lsl #32
+	rev	xMEMBASE, xMEMBASE
+	rev	xMEMSIZE, xMEMSIZE
+	orr	xMEMNODE, xMEMNODE, #HAVE_REG
+	b	inc_and_next_tag
+
+check_device_type:
+	/*
+	 * Check whether the current property's name is 'device_type'
+	 */
+	adr	x4, _device_type
+	bl	strcmp
+	cbnz	w7, inc_and_next_tag
+	orr	xMEMNODE, xMEMNODE, #HAVE_DEVICE_TYPE
+
+inc_and_next_tag:
+	add	xDTP, xDTP, x6
+	b	next_tag
+
+end_node:
+	/*
+	 * Check for device_type = memory and reg = xxxx
+	 * If we have both, we are done
+	 */
+	add	xDTP, xDTP, #4
+	cmp	xMEMNODE, #(HAVE_REG | HAVE_DEVICE_TYPE)
+	bne	next_tag
+
+	ret	xLR
+
+err_invalid_magic:
+err_unexpected_begin_tag:
+err_unexpected_tag:
+err_end_of_fdt:
+	wfi
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/RelocatableVirtHelper.S b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/RelocatableVirtHelper.S
new file mode 100644
index 000000000000..d6edc62efc0d
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/RelocatableVirtHelper.S
@@ -0,0 +1,167 @@ 
+#
+#  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 <Base.h>
+#include <Library/ArmLib.h>
+#include <Library/PcdLib.h>
+#include <AutoGen.h>
+
+.text
+.align 2
+
+GCC_ASM_EXPORT(ArmPlatformPeiBootAction)
+GCC_ASM_EXPORT(ArmPlatformIsPrimaryCore)
+GCC_ASM_EXPORT(ArmPlatformGetPrimaryCoreMpId)
+GCC_ASM_EXPORT(ArmPlatformGetCorePosition)
+GCC_ASM_EXPORT(ArmGetPhysAddrTop)
+
+GCC_ASM_IMPORT(_gPcd_FixedAtBuild_PcdArmPrimaryCore)
+GCC_ASM_IMPORT(_gPcd_FixedAtBuild_PcdArmPrimaryCoreMask)
+GCC_ASM_IMPORT(_gPcd_FixedAtBuild_PcdCoreCount)
+
+.LFdtMagic:
+  .byte   0xd0, 0x0d, 0xfe, 0xed
+
+.LArm64LinuxMagic:
+  .byte   0x41, 0x52, 0x4d, 0x64
+
+// VOID
+// ArmPlatformPeiBootAction (
+//   VOID   *DeviceTreeBaseAddress,   // passed by loader in x0
+//   VOID   *ImageBase                // passed by FDF trampoline in x1
+//   );
+ASM_PFX(ArmPlatformPeiBootAction):
+  mov   x29, x30            // preserve LR
+
+  //
+  // If we are booting from RAM using the Linux kernel boot protocol, x0 will
+  // point to the DTB image in memory. Otherwise, we are just coming out of
+  // reset, and x0 will be 0. Check also the FDT magic.
+  //
+  cbz   x0, .Lout
+  ldr   w8, .LFdtMagic
+  ldr   w9, [x0]
+  cmp   w8, w9
+  bne   .Lout
+
+  //
+  // The base of the runtime image has been preserved in x1. Check whether
+  // the expected magic number can be found in the header.
+  //
+  ldr   w8, .LArm64LinuxMagic
+  ldr   w9, [x1, #0x38]
+  cmp   w8, w9
+  bne   .Lout
+
+  //
+  //
+  // OK, so far so good. We have confirmed that we likely have a DTB and are
+  // booting via the arm64 Linux boot protocol. Update the base-of-image PCD
+  // to the actual relocated value, and add the shift of PcdFdBaseAddress to
+  // PcdFvBaseAddress as well
+  //
+  adr   x8, PcdGet64 (PcdFdBaseAddress)
+  adr   x9, PcdGet64 (PcdFvBaseAddress)
+  ldr   x6, [x8]
+  ldr   x7, [x9]
+  sub   x7, x7, x6
+  add   x7, x7, x1
+  str   x1, [x8]
+  str   x7, [x9]
+
+  //
+  // Copy the DTB to the slack space right after the 64 byte arm64/Linux style
+  // image header at the base of this image (defined in the FDF), and record the
+  // pointer in PcdDeviceTreeInitialBaseAddress.
+  //
+  adr   x8, PcdGet64 (PcdDeviceTreeInitialBaseAddress)
+  add   x1, x1, #0x40
+  str   x1, [x8]
+
+  ldr   w8, [x0, #4]          // get DTB size (BE)
+  mov   x9, x1
+  rev   w8, w8
+  add   x8, x8, x0
+0:ldp   x6, x7, [x0], #16
+  stp   x6, x7, [x9], #16
+  cmp   x0, x8
+  blt   0b
+
+  //
+  // Discover the memory size and offset from the DTB, and record in the
+  // respective PCDs
+  //
+  mov   x0, x1
+  bl    find_memnode    // returns (size, base) size in (x0, x1)
+  cbz   x0, .Lout
+
+  adr   x8, PcdGet64 (PcdSystemMemorySize)
+  adr   x9, PcdGet64 (PcdSystemMemoryBase)
+  str   x0, [x8]
+  str   x1, [x9]
+
+.Lout:
+  ret    x29
+
+//UINTN
+//ArmPlatformGetPrimaryCoreMpId (
+//  VOID
+//  );
+ASM_PFX(ArmPlatformGetPrimaryCoreMpId):
+  LoadConstantToReg (_gPcd_FixedAtBuild_PcdArmPrimaryCore, x0)
+  ldrh   w0, [x0]
+  ret
+
+//UINTN
+//ArmPlatformIsPrimaryCore (
+//  IN UINTN MpId
+//  );
+ASM_PFX(ArmPlatformIsPrimaryCore):
+  mov   x0, #1
+  ret
+
+//UINTN
+//ArmPlatformGetCorePosition (
+//  IN UINTN MpId
+//  );
+// With this function: CorePos = (ClusterId * 4) + CoreId
+ASM_PFX(ArmPlatformGetCorePosition):
+  and   x1, x0, #ARM_CORE_MASK
+  and   x0, x0, #ARM_CLUSTER_MASK
+  add   x0, x1, x0, LSR #6
+  ret
+
+//EFI_PHYSICAL_ADDRESS
+//GetPhysAddrTop (
+//  VOID
+//  );
+ASM_PFX(ArmGetPhysAddrTop):
+  mrs   x0, id_aa64mmfr0_el1
+  adr   x1, .LPARanges
+  and   x0, x0, #7
+  ldrb  w1, [x1, x0]
+  mov   x0, #1
+  lsl   x0, x0, x1
+  ret
+
+//
+// Bits 0..2 of the AA64MFR0_EL1 system register encode the size of the
+// physical address space support on this CPU:
+// 0 == 32 bits, 1 == 36 bits, etc etc
+// 6 and 7 are reserved
+//
+.LPARanges:
+  .byte 32, 36, 40, 42, 44, 48, -1, -1
+
+ASM_FUNCTION_REMOVE_IF_UNREFERENCED
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/ArmXenRelocatablePlatformLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/ArmXenRelocatablePlatformLib.inf
new file mode 100644
index 000000000000..17bb0f9292e2
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/ArmXenRelocatablePlatformLib.inf
@@ -0,0 +1,59 @@ 
+#/* @file
+#  Copyright (c) 2011-2014, ARM Limited. All rights reserved.
+#  Copyright (c) 2014, Linaro 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                      = ArmXenRelocatablePlatformLib
+  FILE_GUID                      = c8602718-4faa-4119-90ca-cae72509ac4c
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = ArmPlatformLib|SEC PEIM
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec
+
+[LibraryClasses]
+  IoLib
+  ArmLib
+  PrintLib
+
+[Sources.common]
+  RelocatableVirt.c
+  XenVirtMem.c
+
+[Sources.AARCH64]
+  AARCH64/RelocatableVirtHelper.S
+  AARCH64/MemnodeParser.S
+
+[FeaturePcd]
+  gEmbeddedTokenSpaceGuid.PcdCacheEnable
+  gArmPlatformTokenSpaceGuid.PcdSystemMemoryInitializeInSec
+
+[PatchPcd]
+  gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress
+  gArmTokenSpaceGuid.PcdFdBaseAddress
+  gArmTokenSpaceGuid.PcdFvBaseAddress
+  gArmTokenSpaceGuid.PcdSystemMemoryBase
+  gArmTokenSpaceGuid.PcdSystemMemorySize
+
+[FixedPcd]
+  gArmPlatformTokenSpaceGuid.PcdCoreCount
+  gArmTokenSpaceGuid.PcdArmPrimaryCoreMask
+  gArmTokenSpaceGuid.PcdArmPrimaryCore
+  gArmTokenSpaceGuid.PcdFdSize
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/RelocatableVirt.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/RelocatableVirt.c
new file mode 100644
index 000000000000..c10c09fed2bd
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/RelocatableVirt.c
@@ -0,0 +1,71 @@ 
+/** @file
+*
+*  Copyright (c) 2011-2013, ARM Limited. All rights reserved.
+*  Copyright (c) 2014, Linaro Limited. All rights reserved.
+*  Copyright (c) 2014, Red Hat, Inc.
+*
+*
+*  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 <ArmPlatform.h>
+#include <Pi/PiBootMode.h>
+
+/**
+  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;
+}
+
+/**
+  This function is called by PrePeiCore, in the SEC phase.
+**/
+RETURN_STATUS
+ArmPlatformInitialize (
+  IN  UINTN                     MpId
+  )
+{
+  //
+  // We are relying on ArmPlatformInitializeSystemMemory () being called from
+  // InitializeMemory (), which only occurs if the following feature is disabled
+  //
+  ASSERT (!FeaturePcdGet (PcdSystemMemoryInitializeInSec));
+  return RETURN_SUCCESS;
+}
+
+VOID
+ArmPlatformInitializeSystemMemory (
+  VOID
+  )
+{
+}
+
+VOID
+ArmPlatformGetPlatformPpiList (
+  OUT UINTN                   *PpiListSize,
+  OUT EFI_PEI_PPI_DESCRIPTOR  **PpiList
+  )
+{
+  *PpiListSize = 0;
+  *PpiList = NULL;
+}
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/XenVirtMem.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/XenVirtMem.c
new file mode 100644
index 000000000000..657b840059c2
--- /dev/null
+++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/XenVirtMem.c
@@ -0,0 +1,83 @@ 
+/** @file
+*
+*  Copyright (c) 2014, Linaro 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/BaseMemoryLib.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          2
+
+// DDR attributes
+#define DDR_ATTRIBUTES_CACHED    ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK
+#define DDR_ATTRIBUTES_UNCACHED  ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED
+
+EFI_PHYSICAL_ADDRESS
+ArmGetPhysAddrTop (
+  VOID
+  );
+
+/**
+  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_DESCRIPTOR  *VirtualMemoryTable;
+
+  ASSERT (VirtualMemoryMap != NULL);
+
+  VirtualMemoryTable = AllocatePages (
+                         EFI_SIZE_TO_PAGES (
+                           sizeof (ARM_MEMORY_REGION_DESCRIPTOR)
+                           * MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS
+                           )
+                         );
+
+  if (VirtualMemoryTable == NULL) {
+    DEBUG ((EFI_D_ERROR, "%a: Error: Failed AllocatePages()\n", __FUNCTION__));
+    return;
+  }
+
+  //
+  // Map the entire physical memory space as cached. The only device
+  // we care about is the GIC, which will be stage 2 mapped as a device
+  // by the hypervisor, which will override the cached mapping we install
+  // here.
+  //
+  VirtualMemoryTable[0].PhysicalBase = 0x0;
+  VirtualMemoryTable[0].VirtualBase  = 0x0;
+  VirtualMemoryTable[0].Length       = ArmGetPhysAddrTop ();
+  VirtualMemoryTable[0].Attributes   = DDR_ATTRIBUTES_CACHED;
+
+  // End of Table
+  ZeroMem (&VirtualMemoryTable[1], sizeof (ARM_MEMORY_REGION_DESCRIPTOR));
+
+  *VirtualMemoryMap = VirtualMemoryTable;
+}