diff mbox

[edk2,v2,7/8] ArmPlatformPkg: add support for a QEMU/mach-virt target

Message ID 1409058229-28802-8-git-send-email-ard.biesheuvel@linaro.org
State New
Headers show

Commit Message

Ard Biesheuvel Aug. 26, 2014, 1:03 p.m. UTC
This adds support for executing UEFI in a QEMU/mach-virt emulated environment.
The following assumptions are made about the target:
- ARM architected timer
- PL011 UART at 0x9000000
- at least 1 MB of DRAM at 0x40000000, containing the device tree blob

The following information is retrieved from the device tree:
- GIC base addresses
- virtual timer interrupt
- RTC base address
- system memory base and size
- virtio MMIO transports

The DTB image is relocated and installed as a configuration table so an
EFI stub enabled kernel can be booted directly without the need for a
bootloader.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Michael Casadevall <michael.casadevall@linaro.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 .../AArch64Virtualization-KVM.dsc                  | 223 +++++++++++++
 .../AArch64Virtualization-KVM.fdf                  | 307 ++++++++++++++++++
 .../AArch64Virtualization.dsc.inc                  | 354 +++++++++++++++++++++
 .../AArch64VirtualizationPkg/Driver/VirtFdt.inf    |  60 ++++
 .../AArch64VirtualizationPkg/Driver/VirtFdtDxe.c   | 229 +++++++++++++
 .../Include/Platform/KVM/ArmPlatform.h             |  32 ++
 .../AArch64VirtualizationLibKVM/AArch64KVMLib.inf  |  53 +++
 .../Library/AArch64VirtualizationLibKVM/KVM.c      | 127 ++++++++
 .../AArch64VirtualizationLibKVM/KVMHelper.S        |  70 ++++
 .../Library/AArch64VirtualizationLibKVM/KVMMem.c   | 106 ++++++
 .../AArch64VirtualizationSysConfigLibKVM.c         |  95 ++++++
 .../AArch64VirtualizationSysConfigLibKVM.inf       |  35 ++
 .../Library/ResetSystemLib/ResetSystemLib.c        |  96 ++++++
 .../Library/ResetSystemLib/ResetSystemLib.inf      |  33 ++
 14 files changed, 1820 insertions(+)
 create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization-KVM.dsc
 create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization-KVM.fdf
 create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization.dsc.inc
 create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdt.inf
 create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdtDxe.c
 create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Include/Platform/KVM/ArmPlatform.h
 create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/AArch64KVMLib.inf
 create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVM.c
 create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMHelper.S
 create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMMem.c
 create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationSysConfigLibKVM/AArch64VirtualizationSysConfigLibKVM.c
 create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationSysConfigLibKVM/AArch64VirtualizationSysConfigLibKVM.inf
 create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.c
 create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.inf

Comments

Laszlo Ersek Aug. 26, 2014, 11:36 p.m. UTC | #1
I'll skip the DSC, FDF and INF files; I assume those are customized
copies from existing platform files. I'll also skip the INF files for now.

On 08/26/14 15:03, Ard Biesheuvel wrote:
> This adds support for executing UEFI in a QEMU/mach-virt emulated environment.
> The following assumptions are made about the target:
> - ARM architected timer
> - PL011 UART at 0x9000000
> - at least 1 MB of DRAM at 0x40000000, containing the device tree blob
> 
> The following information is retrieved from the device tree:
> - GIC base addresses
> - virtual timer interrupt
> - RTC base address
> - system memory base and size
> - virtio MMIO transports
> 
> The DTB image is relocated and installed as a configuration table so an
> EFI stub enabled kernel can be booted directly without the need for a
> bootloader.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Michael Casadevall <michael.casadevall@linaro.org>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>  .../AArch64Virtualization-KVM.dsc                  | 223 +++++++++++++
>  .../AArch64Virtualization-KVM.fdf                  | 307 ++++++++++++++++++
>  .../AArch64Virtualization.dsc.inc                  | 354 +++++++++++++++++++++
>  .../AArch64VirtualizationPkg/Driver/VirtFdt.inf    |  60 ++++
>  .../AArch64VirtualizationPkg/Driver/VirtFdtDxe.c   | 229 +++++++++++++
>  .../Include/Platform/KVM/ArmPlatform.h             |  32 ++
>  .../AArch64VirtualizationLibKVM/AArch64KVMLib.inf  |  53 +++
>  .../Library/AArch64VirtualizationLibKVM/KVM.c      | 127 ++++++++
>  .../AArch64VirtualizationLibKVM/KVMHelper.S        |  70 ++++
>  .../Library/AArch64VirtualizationLibKVM/KVMMem.c   | 106 ++++++
>  .../AArch64VirtualizationSysConfigLibKVM.c         |  95 ++++++
>  .../AArch64VirtualizationSysConfigLibKVM.inf       |  35 ++
>  .../Library/ResetSystemLib/ResetSystemLib.c        |  96 ++++++
>  .../Library/ResetSystemLib/ResetSystemLib.inf      |  33 ++
>  14 files changed, 1820 insertions(+)
>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization-KVM.dsc
>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization-KVM.fdf
>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization.dsc.inc
>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdt.inf
>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdtDxe.c
>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Include/Platform/KVM/ArmPlatform.h
>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/AArch64KVMLib.inf
>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVM.c
>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMHelper.S
>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMMem.c
>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationSysConfigLibKVM/AArch64VirtualizationSysConfigLibKVM.c
>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationSysConfigLibKVM/AArch64VirtualizationSysConfigLibKVM.inf
>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.c
>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.inf

[snip]

> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdtDxe.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdtDxe.c
> new file mode 100644
> index 000000000000..04840e5d1a57
> --- /dev/null
> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdtDxe.c
> @@ -0,0 +1,229 @@
> +/** @file
> +*  Device tree enumeration DXE driver for AArch64 VMs
> +*
> +*  Copyright (c) 2014, 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 <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/UefiDriverEntryPoint.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/VirtioMmioDeviceLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/DxeServicesLib.h>
> +#include <libfdt.h>
> +
> +#include <Guid/Fdt.h>
> +
> +#pragma pack (1)
> +typedef struct {
> +  VENDOR_DEVICE_PATH                  Vendor;
> +  UINT32                              Instance;
> +  EFI_DEVICE_PATH_PROTOCOL            End;
> +} VIRTIO_BLK_DEVICE_PATH;
> +#pragma pack ()

Ugh. :)

Have you seen my earlier patches where the vendor device path node
corresponding to a virtio-mmio transport actually included the base
address of the MMIO register block? I think such a hwvendor devpath node
is much more useful; it can actually help you debug.

In any case, if you decide to stick with this hwvendor devpath node,
plase don't call it VIRTIO_BLK. Call it VIRTIO_MMIO, or
VIRTIO_TRANSPORT, or something else virtio-device-type-agnostic.

> +
> +static struct _Ptypes {
> +  enum _Ptype {
> +    UNKNOWN, GIC, RTC, VIRTIO, UART, TIMER
> +  }         Ptype;
> +  CHAR8     Comp[20];
> +} const Ptypes[] = {
> +  { GIC,     "arm,cortex-a15-gic"  },
> +  { RTC,     "arm,pl031"           },
> +  { VIRTIO,  "virtio,mmio"         },
> +  { UART,    "arm,pl011"           },
> +  { TIMER,   "arm,armv7-timer"     },
> +  { TIMER,   "arm,armv8-timer"     },
> +  { UNKNOWN, ""                    }
> +};

This is a smorgasbord of edk2 coding style violations. Rather than
explaining each, let me just rewrite the definition. I'll assume that
"P" stands for "Property".

typedef enum {
  PropertyTypeUnknown,
  PropertyTypeGic,
  PropertyTypeRtc,
  PropertyTypeVirtio,
  ...
} PROPERTY_TYPE;

typedef struct {
  PROPERTY_TYPE Type;
  CHAR8         Compatible[20];
} PROPERTY;

STATIC CONST PROPERTY[] = {
  ...
};

> +
> +enum _Ptype GetTypeFromNode (CHAR8 CONST *NodeType, INT32 Size)

STATIC
PROPERTY_TYPE
GetTypeFromNode (
  IN CONST CHAR8 *NodeType,
  IN UINTN       Size
  )
{
  ...
}

> +{
> +  CHAR8 CONST *s;

CONST goes first. Please rename "s" to something sensible, and make it
CamelCase.

(... Yes, I know.)

> +
> +  /*
> +   * A 'compatible' node may contain a sequence of NULL terminated
> +   * compatible strings so check each one
> +   */

//
// A 'compatible' node ...
// ...
//

> +  for (s = NodeType; s < NodeType + Size && *s; s += 1 + AsciiStrLen (s)) {
> +    struct _Ptypes const *Type;
> +
> +    for (Type = Ptypes; Type->Comp[0]; Type++)

Braces are mandatory.

> +      if (AsciiStrCmp (Type->Comp, s) == 0)
> +        return Type->Ptype;
> +  }
> +  return UNKNOWN;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +InitializeVirtFdtDxe (
> +  IN EFI_HANDLE           ImageHandle,
> +  IN EFI_SYSTEM_TABLE     *SystemTable
> +  )
> +{
> +  VOID        *FdtImageData;
> +  VOID        *MemoryBase;
> +  INT32       Node, Prev, VirtIoInstance;
> +  EFI_STATUS  Status;
> +
> +  MemoryBase = (VOID *)PcdGet64 (PcdSystemMemoryBase);

Given that this code is exclusively 64-bit, this should be fine.

> +
> +  if (fdt_check_header (MemoryBase) != 0) {
> +    DEBUG ((EFI_D_ERROR, "InitializeVirtFdtDxe: No DTB found @ 0x%08x\n",
> +          MemoryBase));

I suggest "%a" instead of "InitializeVirtFdtDxe" in the format string,
and __FUNCTION__ in the variable argument list, accordingly.

And, referencing my v2 6/8 review, the DTB may have been corrupted by
the time we get here.

> +    return EFI_NOT_FOUND;
> +  }
> +
> +  FdtImageData = AllocatePages (EFI_SIZE_TO_PAGES (fdt_totalsize (MemoryBase)));

What's wrong with AllocatePool()? Does the EFI stub require full pages,
and page alignment?

> +  if (FdtImageData == NULL) {
> +    DEBUG ((EFI_D_ERROR, "InitializeVirtFdtDxe: AllocatePages() failed\n"));

"%a", __FUNCTION

> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  CopyMem (FdtImageData, MemoryBase, fdt_totalsize (MemoryBase));
> +  Status = gBS->InstallConfigurationTable (&gFdtTableGuid, FdtImageData);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  DEBUG ((EFI_D_ERROR, "InitializeVirtFdtDxe: DTB @ 0x%08x\n", FdtImageData));

Yow. The frequent problem of ARM builds, namely that they suppress all
debug messages under EFI_D_ERROR, should not be remedied by printing
everything as EFI_D_ERROR. EFI_D_ERROR should be reserved for, well,
errors. This is an EFI_D_INFO or EFI_D_VERBOSE message.

The problem of over-suppressing is remedied by enabling EFI_D_INFO and
maybe even EFI_D_VERBOSE in the DSC file, PcdDebugPrintErrorLevel.

In addition, the %x format specifier is inappropriate for a pointer. You
should use %p. If you'd like zero padding (and let's then also consider
this is 64-bit code only), then:

  DEBUG ((EFI_D_INFO, "%a: DTB @ 0x%016Lx\n",
    __FUNCTION__, (UINT64)(UINTN)FdtImageData));

> +
> +  /*
> +   * Now enumerate the nodes and install peripherals that we are interested in,
> +   * i.e., GIC, RTC and virtio MMIO nodes
> +   */

//
// comment
//

> +  Status = EFI_SUCCESS;
> +
> +  for (Prev = VirtIoInstance = 0; Status == EFI_SUCCESS; Prev = Node) {

Please say

  Prev = 0;
  VirtIoInstance = 0;


> +    CONST CHAR8                 *Type;
> +    INT32                       Len;

(Usually UINTN is preferred for sizes and lengths.)

> +    enum _Ptype                 Ptype;
> +    VOID CONST                  *RegProp;
> +
> +    Node = fdt_next_node (MemoryBase, Prev, NULL);
> +    if (Node < 0)
> +      break;
> +
> +    Type = fdt_getprop (MemoryBase, Node, "compatible", &Len);
> +    if (Type == NULL)
> +      continue;
> +
> +    Ptype = GetTypeFromNode (Type, Len);
> +    if (Ptype == UNKNOWN)
> +      continue;
> +
> +    /*
> +     * Get the 'reg' property of this node. For now, we will assume
> +     * 8 byte quantities for base and size, respectively.
> +     * TODO use #cells root properties instead
> +     */

Prior comments apply (braces, CONST, comment style, etc).

> +    RegProp = fdt_getprop (MemoryBase, Node, "reg", &Len);
> +    ASSERT (RegProp != NULL || Ptype == TIMER);
> +
> +    switch (Ptype) {
> +      VIRTIO_BLK_DEVICE_PATH  *DevicePath;
> +      EFI_HANDLE              Handle;
> +      UINT64                  RegBase;
> +      UINT32                  DistBase, CpuBase;

Yikes! Definition of automatic storage duration objects in a switch
block. Very valid, yet very unacceptable for edk2. :) Please move them out.

> +      
> +    case VIRTIO:
> +      /* Create a unique device path for this transport on the fly */

//
// comment
//

> +      DevicePath = (VIRTIO_BLK_DEVICE_PATH *)CreateDeviceNode (
> +                                    HARDWARE_DEVICE_PATH,
> +                                    HW_VENDOR_DP,
> +                                    sizeof (VIRTIO_BLK_DEVICE_PATH));
> +
> +      CopyMem (&DevicePath->Vendor.Guid, &gEfiCallerIdGuid, sizeof (EFI_GUID));
> +      DevicePath->Instance = VirtIoInstance++;
> +      SetDevicePathNodeLength (&DevicePath->Vendor,
> +                              sizeof (*DevicePath) - sizeof (DevicePath->End));
> +      SetDevicePathEndNode (&DevicePath->End);

Seems sane.

> +
> +      Handle = NULL;
> +      Status = gBS->InstallProtocolInterface (&Handle,
> +                     &gEfiDevicePathProtocolGuid, EFI_NATIVE_INTERFACE,
> +                     DevicePath);
> +      if (EFI_ERROR (Status)) {
> +        DEBUG ((EFI_D_ERROR, "Failed to install VirtIO protocol interface\n"));
> +        break;
> +      }

Incorrect error message; what failed was the handle creation (requested
by installing a devpath on an initially NULL handle).

Also, if this fails, we'll correctly terminate the loop. However we will
also simply leave the function without undoing / rolling back the virtio
installations that did succeed. This may or may not be intended.

> +
> +      RegBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);
> +      Status = VirtioMmioInstallDevice (RegBase, Handle);
> +      if (EFI_ERROR (Status))
> +        DEBUG ((EFI_D_ERROR, "Failed to install VirtIO transport @ 0x%x\n",
> +                RegBase));

0x%Lx (or lx, as you prefer)

> +      break;
> +
> +    case GIC:
> +      ASSERT (Len == 32);
> +
> +      DistBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);
> +      CpuBase = fdt64_to_cpu (((UINT64 *)RegProp)[2]);
> +      PcdSet32 (PcdGicDistributorBase, DistBase);
> +      PcdSet32 (PcdGicInterruptInterfaceBase, CpuBase);

DistBase and CpuBase are UINT32s, matching the PCDs, but they don't
match the FDT (UINT64). Is that okay?

> +
> +      DEBUG ((EFI_D_ERROR, "Found GIC @ 0x%x/0x%x\n", DistBase, CpuBase));

EFI_D_INFO

> +      break;
> +
> +    case RTC:
> +      ASSERT (Len == 16);
> +      
> +      RegBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);
> +      PcdSet32 (PcdPL031RtcBase, (UINT32)RegBase);

Since we're asserting the length, we could also assert that conversion
to UINT32 doesn't cause truncation.

> +
> +      DEBUG ((EFI_D_ERROR, "Found PL031 RTC @ 0x%x\n", RegBase));

EFI_D_INFO, 0x%Lx

> +      break;
> +
> +    case TIMER: {
> +      struct {
> +        UINT32  Type;
> +        UINT32  Number;
> +        UINT32  Flags;
> +      } const *Interrupts;

please move the struct def out, and give it a typedef, as seen above

> +      INT32 SecIntrNum, IntrNum, VirtIntrNum, HypIntrNum;
> +
> +      /*
> +       * - interrupts : Interrupt list for secure, non-secure, virtual and
> +       *  hypervisor timers, in that order.
> +       */

//
// comment
//

> +      Interrupts = fdt_getprop (MemoryBase, Node, "interrupts", &Len);
> +      ASSERT (Len == 48);
> +
> +      SecIntrNum = fdt32_to_cpu (Interrupts[0].Number)
> +                   + (Interrupts[0].Type ? 16 : 0);
> +      IntrNum = fdt32_to_cpu (Interrupts[1].Number)
> +                + (Interrupts[1].Type ? 16 : 0);
> +      VirtIntrNum = fdt32_to_cpu (Interrupts[2].Number)
> +                    + (Interrupts[2].Type ? 16 : 0);
> +      HypIntrNum = fdt32_to_cpu (Interrupts[3].Number)
> +                   + (Interrupts[3].Type ? 16 : 0);
> +      
> +      DEBUG ((EFI_D_ERROR, "Found Timer interrupts %d, %d, %d, %d\n",
> +        SecIntrNum, IntrNum, VirtIntrNum, HypIntrNum));
> +
> +      PcdSet32 (PcdArmArchTimerSecIntrNum, SecIntrNum);
> +      PcdSet32 (PcdArmArchTimerIntrNum, IntrNum);
> +      PcdSet32 (PcdArmArchTimerVirtIntrNum, VirtIntrNum);
> +      PcdSet32 (PcdArmArchTimerHypIntrNum, HypIntrNum);
> +      break;
> +    }
> +
> +    default:
> +      break;
> +    }
> +  }
> +  return Status;
> +}


[snip]


> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVM.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVM.c
> new file mode 100644
> index 000000000000..dcbe076f5d58
> --- /dev/null
> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVM.c
> @@ -0,0 +1,127 @@
> +/** @file
> +*
> +*  Copyright (c) 2011-2013, 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.
> +*
> +**/
> +
> +#include <Library/IoLib.h>
> +#include <Library/ArmPlatformLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/PcdLib.h>
> +#include <ArmPlatform.h>
> +#include <libfdt.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;
> +}
> +
> +/**
> +  Initialize controllers that must setup in the normal world
> +
> +  This function is called by the ArmPlatformPkg/Pei or ArmPlatformPkg/Pei/PlatformPeim
> +  in the PEI phase.
> +
> +**/
> +RETURN_STATUS
> +ArmPlatformInitialize (
> +  IN  UINTN                     MpId
> +  )
> +{
> +  return RETURN_SUCCESS;
> +}
> +
> +/**
> +  Initialize the system (or sometimes called permanent) memory
> +
> +  This memory is generally represented by the DRAM.
> +
> +**/
> +VOID
> +ArmPlatformInitializeSystemMemory (
> +  VOID
> +  )
> +{
> +  VOID   *SystemMemoryBase;
> +  INT32   Node, Prev;
> +
> +  SystemMemoryBase = (VOID *)PcdGet64 (PcdSystemMemoryBase);
> +
> +  /*
> +   * Make sure we have a valid device tree blob at the base of DRAM
> +   */
> +  if (fdt_check_header (SystemMemoryBase) != 0)
> +    return;
> +
> +  /*
> +   * Look for a memory node
> +   * TODO handle disjoint memory
> +   */
> +  for (Prev = 0;; Prev = Node) {
> +    CONST CHAR8  *Type;
> +    INT32         Len;
> +
> +    Node = fdt_next_node (SystemMemoryBase, Prev, NULL);
> +    if (Node < 0)
> +      return;
> +
> +    Type = fdt_getprop (SystemMemoryBase, Node, "device_type", &Len);
> +    if (Type && AsciiStrnCmp (Type, "memory", Len) == 0) {
> +      UINT64 CONST *RegProp;
> +
> +      /*
> +       * Get the 'reg' property of this node. For now, we will assume
> +       * two 8 byte quantities for base and size, respectively.
> +       * TODO use #cells root properties instead
> +       */
> +      RegProp = fdt_getprop (SystemMemoryBase, Node, "reg", &Len);
> +      if (RegProp != 0 && Len == (2 * sizeof (UINT64))) {
> +        UINT64 NewBase, NewSize;
> +
> +        NewBase = fdt64_to_cpu (RegProp[0]);
> +        NewSize = fdt64_to_cpu (RegProp[1]);
> +
> +        PcdSet64 (PcdSystemMemoryBase, NewBase);
> +        PcdSet64 (PcdSystemMemorySize, NewSize);
> +
> +        DEBUG ((EFI_D_ERROR, "KVM: System RAM @ 0x%lx - 0x%lx\n",
> +           NewBase, NewBase + NewSize - 1));
> +      }
> +      continue;
> +    }
> +  }
> +}

Too tired to check semantics overly deeply. Prior style remarks apply.

In addition, I think the "continue" is superfluous.


> +
> +EFI_PEI_PPI_DESCRIPTOR      gPlatformPpiTable[] = {
> +};

GNUism, please avoid. Please spell out

... gPlatformPpiTable[] = { { 0 } };

> +
> +VOID
> +ArmPlatformGetPlatformPpiList (
> +  OUT UINTN                   *PpiListSize,
> +  OUT EFI_PEI_PPI_DESCRIPTOR  **PpiList
> +  )
> +{
> +  *PpiListSize = sizeof (gPlatformPpiTable);
> +  *PpiList = gPlatformPpiTable;
> +}

[snip KVMHelper.S]

> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMMem.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMMem.c
> new file mode 100644
> index 000000000000..55dcf31a5666
> --- /dev/null
> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMMem.c
> @@ -0,0 +1,106 @@
> +/** @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/ArmPlatformLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/ArmPlatformGlobalVariableLib.h>
> +#include <ArmPlatform.h>
> +
> +// Number of Virtual Memory Map Descriptors without a Logic Tile
> +#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS          4
> +
> +// 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;
> +  ARM_MEMORY_REGION_DESCRIPTOR  *VirtualMemoryTable;
> +  EFI_PHYSICAL_ADDRESS          PhysAddrTop;
> +
> +  static INT16 const PARange[] = { 32, 36, 40, 42, 44, 48, -1, -1 };
> +
> +  ASSERT (VirtualMemoryMap != NULL);
> +
> +  /*
> +   * Get the max phys address from the CPU config registers
> +   */
> +  asm ("mrs  %0, id_aa64mmfr0_el1" : "=r" (PhysAddrTop));

This should be moved into a dedicated helper function / assembly
language file.

> +  PhysAddrTop = 1ULL << PARange[PhysAddrTop & 7];
> +  ASSERT (PhysAddrTop != 0);
> +
> +  VirtualMemoryTable = AllocatePages (EFI_SIZE_TO_PAGES (
> +                                     sizeof (ARM_MEMORY_REGION_DESCRIPTOR)
> +                                     * MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS));
> +  if (VirtualMemoryTable == NULL) {
> +	  DEBUG ((EFI_D_ERROR, "ArmPlatformGetVirtualMemoryMap: Error: Failed AllocatePages()\n"));
> +      return;
> +  }
> +
> +  if (FeaturePcdGet (PcdCacheEnable) == TRUE) {
> +      CacheAttributes = DDR_ATTRIBUTES_CACHED;
> +  } else {
> +      CacheAttributes = DDR_ATTRIBUTES_UNCACHED;
> +  }
> +
> +  // System DRAM
> +  VirtualMemoryTable[0].PhysicalBase = PcdGet64 (PcdSystemMemoryBase);
> +  VirtualMemoryTable[0].VirtualBase  = VirtualMemoryTable[0].PhysicalBase;
> +  VirtualMemoryTable[0].Length       = PcdGet64 (PcdSystemMemorySize);
> +  VirtualMemoryTable[0].Attributes   = CacheAttributes;
> +
> +  DEBUG ((EFI_D_ERROR, "ArmPlatformGetVirtualMemoryMap: Dumping DDR Memory Map:\n \
> +		  DDR PhysicalBase: 0x%lX\n \
> +		  VirtualBase: 0x%lX\n \
> +		  Length: 0x%lX\n",
> +		  VirtualMemoryTable[0].PhysicalBase,
> +		  VirtualMemoryTable[0].VirtualBase,
> +		  VirtualMemoryTable[0].Length));
> +
> +  // Peripheral space before DRAM
> +  VirtualMemoryTable[1].PhysicalBase = 0x0;
> +  VirtualMemoryTable[1].VirtualBase  = 0x0;
> +  VirtualMemoryTable[1].Length       = VirtualMemoryTable[0].PhysicalBase;
> +  VirtualMemoryTable[1].Attributes   = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
> +
> +  // Peripheral space after DRAM
> +  VirtualMemoryTable[2].PhysicalBase = VirtualMemoryTable[0].Length + VirtualMemoryTable[1].Length;
> +  VirtualMemoryTable[2].VirtualBase  = VirtualMemoryTable[2].PhysicalBase;
> +  VirtualMemoryTable[2].Length       = PhysAddrTop - VirtualMemoryTable[2].PhysicalBase;
> +  VirtualMemoryTable[2].Attributes   = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
> +
> +  // End of Table
> +  VirtualMemoryTable[3] = (ARM_MEMORY_REGION_DESCRIPTOR){};
> +
> +  *VirtualMemoryMap = VirtualMemoryTable;
> +}

No comments as to validity, but style observations apply. In particular,
kill those line-trailing backslashes, please; it's "perfectly possible "
"to " "concatenate string " "literals".

[snip]

> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.c
> new file mode 100644
> index 000000000000..e5edbc407b56
> --- /dev/null
> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.c
> @@ -0,0 +1,96 @@
> +/** @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>
> +
> +  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/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/EfiResetSystemLib.h>
> +
> +#include <ArmPlatform.h>
> +
> +/**
> +  Resets the entire platform.
> +
> +  @param  ResetType             The type of reset to perform.
> +  @param  ResetStatus           The status code for the reset.
> +  @param  DataSize              The size, in bytes, of WatchdogData.
> +  @param  ResetData             For a ResetType of EfiResetCold, EfiResetWarm, or
> +                                EfiResetShutdown the data buffer starts with a Null-terminated
> +                                Unicode string, optionally followed by additional binary data.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +LibResetSystem (
> +  IN EFI_RESET_TYPE   ResetType,
> +  IN EFI_STATUS       ResetStatus,
> +  IN UINTN            DataSize,
> +  IN CHAR16           *ResetData OPTIONAL
> +  )
> +{
> +  register UINTN Rx asm ("x0");
> +
> +  switch (ResetType) {
> +
> +  case EfiResetPlatformSpecific:
> +    // Map the platform specific reset as reboot
> +  case EfiResetWarm:
> +    // Map a warm reset into a cold reset
> +  case EfiResetCold:
> +    // Send a PSCI 0.2 SYSTEM_RESET command
> +    Rx = PSCI_0_2_FN_SYSTEM_RESET;
> +    break;
> +  case EfiResetShutdown:
> +    // Send a PSCI 0.2 SYSTEM_OFF command
> +    Rx = PSCI_0_2_FN_SYSTEM_OFF;
> +    break;
> +
> +  default:
> +    ASSERT (FALSE);
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  /*
> +   * Being a virtualized platform, we are allowed to assume that we
> +   * are running at EL1, so HVC is appropriate for making PSCI calls.
> +   */
> +  asm ("hvc #0" :: "r" (Rx));

Should be a separate... etc etc

> +
> +  // We should never be here
> +  while (1);
> +}

CpuDeadLoop() is more idiomatic in edk2.

> +
> +/**
> +  Initialize any infrastructure required for LibResetSystem () to function.
> +
> +  @param  ImageHandle   The firmware allocated handle for the EFI image.
> +  @param  SystemTable   A pointer to the EFI System Table.
> +  
> +  @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +LibInitializeResetSystem (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  return EFI_SUCCESS;
> +}

Thanks
Laszlo

------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Ard Biesheuvel Aug. 27, 2014, 8:27 a.m. UTC | #2
On 27 August 2014 01:36, Laszlo Ersek <lersek@redhat.com> wrote:
> I'll skip the DSC, FDF and INF files; I assume those are customized
> copies from existing platform files. I'll also skip the INF files for now.
>
> On 08/26/14 15:03, Ard Biesheuvel wrote:
>> This adds support for executing UEFI in a QEMU/mach-virt emulated environment.
>> The following assumptions are made about the target:
>> - ARM architected timer
>> - PL011 UART at 0x9000000
>> - at least 1 MB of DRAM at 0x40000000, containing the device tree blob
>>
>> The following information is retrieved from the device tree:
>> - GIC base addresses
>> - virtual timer interrupt
>> - RTC base address
>> - system memory base and size
>> - virtio MMIO transports
>>
>> The DTB image is relocated and installed as a configuration table so an
>> EFI stub enabled kernel can be booted directly without the need for a
>> bootloader.
>>
>> Contributed-under: TianoCore Contribution Agreement 1.0
>> Signed-off-by: Michael Casadevall <michael.casadevall@linaro.org>
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> ---
>>  .../AArch64Virtualization-KVM.dsc                  | 223 +++++++++++++
>>  .../AArch64Virtualization-KVM.fdf                  | 307 ++++++++++++++++++
>>  .../AArch64Virtualization.dsc.inc                  | 354 +++++++++++++++++++++
>>  .../AArch64VirtualizationPkg/Driver/VirtFdt.inf    |  60 ++++
>>  .../AArch64VirtualizationPkg/Driver/VirtFdtDxe.c   | 229 +++++++++++++
>>  .../Include/Platform/KVM/ArmPlatform.h             |  32 ++
>>  .../AArch64VirtualizationLibKVM/AArch64KVMLib.inf  |  53 +++
>>  .../Library/AArch64VirtualizationLibKVM/KVM.c      | 127 ++++++++
>>  .../AArch64VirtualizationLibKVM/KVMHelper.S        |  70 ++++
>>  .../Library/AArch64VirtualizationLibKVM/KVMMem.c   | 106 ++++++
>>  .../AArch64VirtualizationSysConfigLibKVM.c         |  95 ++++++
>>  .../AArch64VirtualizationSysConfigLibKVM.inf       |  35 ++
>>  .../Library/ResetSystemLib/ResetSystemLib.c        |  96 ++++++
>>  .../Library/ResetSystemLib/ResetSystemLib.inf      |  33 ++
>>  14 files changed, 1820 insertions(+)
>>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization-KVM.dsc
>>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization-KVM.fdf
>>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization.dsc.inc
>>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdt.inf
>>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdtDxe.c
>>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Include/Platform/KVM/ArmPlatform.h
>>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/AArch64KVMLib.inf
>>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVM.c
>>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMHelper.S
>>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMMem.c
>>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationSysConfigLibKVM/AArch64VirtualizationSysConfigLibKVM.c
>>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationSysConfigLibKVM/AArch64VirtualizationSysConfigLibKVM.inf
>>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.c
>>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.inf
>
> [snip]
>
>> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdtDxe.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdtDxe.c
>> new file mode 100644
>> index 000000000000..04840e5d1a57
>> --- /dev/null
>> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdtDxe.c
>> @@ -0,0 +1,229 @@
>> +/** @file
>> +*  Device tree enumeration DXE driver for AArch64 VMs
>> +*
>> +*  Copyright (c) 2014, 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 <Library/BaseLib.h>
>> +#include <Library/DebugLib.h>
>> +#include <Library/UefiLib.h>
>> +#include <Library/BaseMemoryLib.h>
>> +#include <Library/UefiDriverEntryPoint.h>
>> +#include <Library/MemoryAllocationLib.h>
>> +#include <Library/UefiBootServicesTableLib.h>
>> +#include <Library/VirtioMmioDeviceLib.h>
>> +#include <Library/DevicePathLib.h>
>> +#include <Library/PcdLib.h>
>> +#include <Library/DxeServicesLib.h>
>> +#include <libfdt.h>
>> +
>> +#include <Guid/Fdt.h>
>> +
>> +#pragma pack (1)
>> +typedef struct {
>> +  VENDOR_DEVICE_PATH                  Vendor;
>> +  UINT32                              Instance;
>> +  EFI_DEVICE_PATH_PROTOCOL            End;
>> +} VIRTIO_BLK_DEVICE_PATH;
>> +#pragma pack ()
>
> Ugh. :)
>
> Have you seen my earlier patches where the vendor device path node
> corresponding to a virtio-mmio transport actually included the base
> address of the MMIO register block? I think such a hwvendor devpath node
> is much more useful; it can actually help you debug.
>

I will just stick a EFI_PHYSICAL_ADDRESS in there instead, or would
you prefer UINT64?

> In any case, if you decide to stick with this hwvendor devpath node,
> plase don't call it VIRTIO_BLK. Call it VIRTIO_MMIO, or
> VIRTIO_TRANSPORT, or something else virtio-device-type-agnostic.
>
>> +
>> +static struct _Ptypes {
>> +  enum _Ptype {
>> +    UNKNOWN, GIC, RTC, VIRTIO, UART, TIMER
>> +  }         Ptype;
>> +  CHAR8     Comp[20];
>> +} const Ptypes[] = {
>> +  { GIC,     "arm,cortex-a15-gic"  },
>> +  { RTC,     "arm,pl031"           },
>> +  { VIRTIO,  "virtio,mmio"         },
>> +  { UART,    "arm,pl011"           },
>> +  { TIMER,   "arm,armv7-timer"     },
>> +  { TIMER,   "arm,armv8-timer"     },
>> +  { UNKNOWN, ""                    }
>> +};
>
> This is a smorgasbord of edk2 coding style violations. Rather than
> explaining each, let me just rewrite the definition. I'll assume that
> "P" stands for "Property".
>
> typedef enum {
>   PropertyTypeUnknown,
>   PropertyTypeGic,
>   PropertyTypeRtc,
>   PropertyTypeVirtio,
>   ...
> } PROPERTY_TYPE;
>
> typedef struct {
>   PROPERTY_TYPE Type;
>   CHAR8         Compatible[20];
> } PROPERTY;
>
> STATIC CONST PROPERTY[] = {
>   ...
> };
>
>> +
>> +enum _Ptype GetTypeFromNode (CHAR8 CONST *NodeType, INT32 Size)
>
> STATIC
> PROPERTY_TYPE
> GetTypeFromNode (
>   IN CONST CHAR8 *NodeType,
>   IN UINTN       Size
>   )
> {
>   ...
> }
>
>> +{
>> +  CHAR8 CONST *s;
>
> CONST goes first. Please rename "s" to something sensible, and make it
> CamelCase.
>
> (... Yes, I know.)
>

OK, thanks, will fix it up

>> +
>> +  /*
>> +   * A 'compatible' node may contain a sequence of NULL terminated
>> +   * compatible strings so check each one
>> +   */
>
> //
> // A 'compatible' node ...
> // ...
> //
>

ok

>> +  for (s = NodeType; s < NodeType + Size && *s; s += 1 + AsciiStrLen (s)) {
>> +    struct _Ptypes const *Type;
>> +
>> +    for (Type = Ptypes; Type->Comp[0]; Type++)
>
> Braces are mandatory.
>

ok

>> +      if (AsciiStrCmp (Type->Comp, s) == 0)
>> +        return Type->Ptype;
>> +  }
>> +  return UNKNOWN;
>> +}
>> +
>> +EFI_STATUS
>> +EFIAPI
>> +InitializeVirtFdtDxe (
>> +  IN EFI_HANDLE           ImageHandle,
>> +  IN EFI_SYSTEM_TABLE     *SystemTable
>> +  )
>> +{
>> +  VOID        *FdtImageData;
>> +  VOID        *MemoryBase;
>> +  INT32       Node, Prev, VirtIoInstance;
>> +  EFI_STATUS  Status;
>> +
>> +  MemoryBase = (VOID *)PcdGet64 (PcdSystemMemoryBase);
>
> Given that this code is exclusively 64-bit, this should be fine.
>
>> +
>> +  if (fdt_check_header (MemoryBase) != 0) {
>> +    DEBUG ((EFI_D_ERROR, "InitializeVirtFdtDxe: No DTB found @ 0x%08x\n",
>> +          MemoryBase));
>
> I suggest "%a" instead of "InitializeVirtFdtDxe" in the format string,
> and __FUNCTION__ in the variable argument list, accordingly.
>
> And, referencing my v2 6/8 review, the DTB may have been corrupted by
> the time we get here.
>
>> +    return EFI_NOT_FOUND;
>> +  }
>> +
>> +  FdtImageData = AllocatePages (EFI_SIZE_TO_PAGES (fdt_totalsize (MemoryBase)));
>
> What's wrong with AllocatePool()? Does the EFI stub require full pages,
> and page alignment?
>

No, AllocatePool() should be fine. This was already in the code I
inherited from Michael Casadevall, so I didn't think about it twice.

>> +  if (FdtImageData == NULL) {
>> +    DEBUG ((EFI_D_ERROR, "InitializeVirtFdtDxe: AllocatePages() failed\n"));
>
> "%a", __FUNCTION
>
>> +    return EFI_OUT_OF_RESOURCES;
>> +  }
>> +
>> +  CopyMem (FdtImageData, MemoryBase, fdt_totalsize (MemoryBase));
>> +  Status = gBS->InstallConfigurationTable (&gFdtTableGuid, FdtImageData);
>> +  ASSERT_EFI_ERROR (Status);
>> +
>> +  DEBUG ((EFI_D_ERROR, "InitializeVirtFdtDxe: DTB @ 0x%08x\n", FdtImageData));
>
> Yow. The frequent problem of ARM builds, namely that they suppress all
> debug messages under EFI_D_ERROR, should not be remedied by printing
> everything as EFI_D_ERROR. EFI_D_ERROR should be reserved for, well,
> errors. This is an EFI_D_INFO or EFI_D_VERBOSE message.
>
> The problem of over-suppressing is remedied by enabling EFI_D_INFO and
> maybe even EFI_D_VERBOSE in the DSC file, PcdDebugPrintErrorLevel.
>

ok

> In addition, the %x format specifier is inappropriate for a pointer. You
> should use %p. If you'd like zero padding (and let's then also consider
> this is 64-bit code only), then:
>
>   DEBUG ((EFI_D_INFO, "%a: DTB @ 0x%016Lx\n",
>     __FUNCTION__, (UINT64)(UINTN)FdtImageData));
>

ok

>> +
>> +  /*
>> +   * Now enumerate the nodes and install peripherals that we are interested in,
>> +   * i.e., GIC, RTC and virtio MMIO nodes
>> +   */
>
> //
> // comment
> //
>
>> +  Status = EFI_SUCCESS;
>> +
>> +  for (Prev = VirtIoInstance = 0; Status == EFI_SUCCESS; Prev = Node) {
>
> Please say
>
>   Prev = 0;
>   VirtIoInstance = 0;
>
>

VirtIoInstance will be removed anyway

>> +    CONST CHAR8                 *Type;
>> +    INT32                       Len;
>
> (Usually UINTN is preferred for sizes and lengths.)
>
>> +    enum _Ptype                 Ptype;
>> +    VOID CONST                  *RegProp;
>> +
>> +    Node = fdt_next_node (MemoryBase, Prev, NULL);
>> +    if (Node < 0)
>> +      break;
>> +
>> +    Type = fdt_getprop (MemoryBase, Node, "compatible", &Len);
>> +    if (Type == NULL)
>> +      continue;
>> +
>> +    Ptype = GetTypeFromNode (Type, Len);
>> +    if (Ptype == UNKNOWN)
>> +      continue;
>> +
>> +    /*
>> +     * Get the 'reg' property of this node. For now, we will assume
>> +     * 8 byte quantities for base and size, respectively.
>> +     * TODO use #cells root properties instead
>> +     */
>
> Prior comments apply (braces, CONST, comment style, etc).
>
>> +    RegProp = fdt_getprop (MemoryBase, Node, "reg", &Len);
>> +    ASSERT (RegProp != NULL || Ptype == TIMER);
>> +
>> +    switch (Ptype) {
>> +      VIRTIO_BLK_DEVICE_PATH  *DevicePath;
>> +      EFI_HANDLE              Handle;
>> +      UINT64                  RegBase;
>> +      UINT32                  DistBase, CpuBase;
>
> Yikes! Definition of automatic storage duration objects in a switch
> block. Very valid, yet very unacceptable for edk2. :) Please move them out.
>
>> +
>> +    case VIRTIO:
>> +      /* Create a unique device path for this transport on the fly */
>
> //
> // comment
> //
>
>> +      DevicePath = (VIRTIO_BLK_DEVICE_PATH *)CreateDeviceNode (
>> +                                    HARDWARE_DEVICE_PATH,
>> +                                    HW_VENDOR_DP,
>> +                                    sizeof (VIRTIO_BLK_DEVICE_PATH));
>> +
>> +      CopyMem (&DevicePath->Vendor.Guid, &gEfiCallerIdGuid, sizeof (EFI_GUID));
>> +      DevicePath->Instance = VirtIoInstance++;
>> +      SetDevicePathNodeLength (&DevicePath->Vendor,
>> +                              sizeof (*DevicePath) - sizeof (DevicePath->End));
>> +      SetDevicePathEndNode (&DevicePath->End);
>
> Seems sane.
>
>> +
>> +      Handle = NULL;
>> +      Status = gBS->InstallProtocolInterface (&Handle,
>> +                     &gEfiDevicePathProtocolGuid, EFI_NATIVE_INTERFACE,
>> +                     DevicePath);
>> +      if (EFI_ERROR (Status)) {
>> +        DEBUG ((EFI_D_ERROR, "Failed to install VirtIO protocol interface\n"));
>> +        break;
>> +      }
>
> Incorrect error message; what failed was the handle creation (requested
> by installing a devpath on an initially NULL handle).
>
> Also, if this fails, we'll correctly terminate the loop. However we will
> also simply leave the function without undoing / rolling back the virtio
> installations that did succeed. This may or may not be intended.
>

I will check the logic carefully. What should happen is that the
traversal of the device tree should proceed, so other peripherals are
detected and installed even if the virtio transports are not.

>> +
>> +      RegBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);
>> +      Status = VirtioMmioInstallDevice (RegBase, Handle);
>> +      if (EFI_ERROR (Status))
>> +        DEBUG ((EFI_D_ERROR, "Failed to install VirtIO transport @ 0x%x\n",
>> +                RegBase));
>
> 0x%Lx (or lx, as you prefer)
>
>> +      break;
>> +
>> +    case GIC:
>> +      ASSERT (Len == 32);
>> +
>> +      DistBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);
>> +      CpuBase = fdt64_to_cpu (((UINT64 *)RegProp)[2]);
>> +      PcdSet32 (PcdGicDistributorBase, DistBase);
>> +      PcdSet32 (PcdGicInterruptInterfaceBase, CpuBase);
>
> DistBase and CpuBase are UINT32s, matching the PCDs, but they don't
> match the FDT (UINT64). Is that okay?
>

Well, it is highly unlikely that peripherals like GIC would be moved
beyond 4 GB in the physical address space, and the device tree just
uses 64-bit addresses in this instantiation, so for now, I think this
is fine. Otherwise, we should update the GIC driver to use UINT64
instead.

>> +
>> +      DEBUG ((EFI_D_ERROR, "Found GIC @ 0x%x/0x%x\n", DistBase, CpuBase));
>
> EFI_D_INFO
>
>> +      break;
>> +
>> +    case RTC:
>> +      ASSERT (Len == 16);
>> +
>> +      RegBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);
>> +      PcdSet32 (PcdPL031RtcBase, (UINT32)RegBase);
>
> Since we're asserting the length, we could also assert that conversion
> to UINT32 doesn't cause truncation.
>

Same applies as above, I will try to clean this up in a more consistent manner.

>> +
>> +      DEBUG ((EFI_D_ERROR, "Found PL031 RTC @ 0x%x\n", RegBase));
>
> EFI_D_INFO, 0x%Lx
>
>> +      break;
>> +
>> +    case TIMER: {
>> +      struct {
>> +        UINT32  Type;
>> +        UINT32  Number;
>> +        UINT32  Flags;
>> +      } const *Interrupts;
>
> please move the struct def out, and give it a typedef, as seen above
>

ok

>> +      INT32 SecIntrNum, IntrNum, VirtIntrNum, HypIntrNum;
>> +
>> +      /*
>> +       * - interrupts : Interrupt list for secure, non-secure, virtual and
>> +       *  hypervisor timers, in that order.
>> +       */
>
> //
> // comment
> //
>
>> +      Interrupts = fdt_getprop (MemoryBase, Node, "interrupts", &Len);
>> +      ASSERT (Len == 48);
>> +
>> +      SecIntrNum = fdt32_to_cpu (Interrupts[0].Number)
>> +                   + (Interrupts[0].Type ? 16 : 0);
>> +      IntrNum = fdt32_to_cpu (Interrupts[1].Number)
>> +                + (Interrupts[1].Type ? 16 : 0);
>> +      VirtIntrNum = fdt32_to_cpu (Interrupts[2].Number)
>> +                    + (Interrupts[2].Type ? 16 : 0);
>> +      HypIntrNum = fdt32_to_cpu (Interrupts[3].Number)
>> +                   + (Interrupts[3].Type ? 16 : 0);
>> +
>> +      DEBUG ((EFI_D_ERROR, "Found Timer interrupts %d, %d, %d, %d\n",
>> +        SecIntrNum, IntrNum, VirtIntrNum, HypIntrNum));
>> +
>> +      PcdSet32 (PcdArmArchTimerSecIntrNum, SecIntrNum);
>> +      PcdSet32 (PcdArmArchTimerIntrNum, IntrNum);
>> +      PcdSet32 (PcdArmArchTimerVirtIntrNum, VirtIntrNum);
>> +      PcdSet32 (PcdArmArchTimerHypIntrNum, HypIntrNum);
>> +      break;
>> +    }
>> +
>> +    default:
>> +      break;
>> +    }
>> +  }
>> +  return Status;
>> +}
>
>
> [snip]
>
>
>> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVM.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVM.c
>> new file mode 100644
>> index 000000000000..dcbe076f5d58
>> --- /dev/null
>> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVM.c
>> @@ -0,0 +1,127 @@
>> +/** @file
>> +*
>> +*  Copyright (c) 2011-2013, 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.
>> +*
>> +**/
>> +
>> +#include <Library/IoLib.h>
>> +#include <Library/ArmPlatformLib.h>
>> +#include <Library/DebugLib.h>
>> +#include <Library/PcdLib.h>
>> +#include <ArmPlatform.h>
>> +#include <libfdt.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;
>> +}
>> +
>> +/**
>> +  Initialize controllers that must setup in the normal world
>> +
>> +  This function is called by the ArmPlatformPkg/Pei or ArmPlatformPkg/Pei/PlatformPeim
>> +  in the PEI phase.
>> +
>> +**/
>> +RETURN_STATUS
>> +ArmPlatformInitialize (
>> +  IN  UINTN                     MpId
>> +  )
>> +{
>> +  return RETURN_SUCCESS;
>> +}
>> +
>> +/**
>> +  Initialize the system (or sometimes called permanent) memory
>> +
>> +  This memory is generally represented by the DRAM.
>> +
>> +**/
>> +VOID
>> +ArmPlatformInitializeSystemMemory (
>> +  VOID
>> +  )
>> +{
>> +  VOID   *SystemMemoryBase;
>> +  INT32   Node, Prev;
>> +
>> +  SystemMemoryBase = (VOID *)PcdGet64 (PcdSystemMemoryBase);
>> +
>> +  /*
>> +   * Make sure we have a valid device tree blob at the base of DRAM
>> +   */
>> +  if (fdt_check_header (SystemMemoryBase) != 0)
>> +    return;
>> +
>> +  /*
>> +   * Look for a memory node
>> +   * TODO handle disjoint memory
>> +   */
>> +  for (Prev = 0;; Prev = Node) {
>> +    CONST CHAR8  *Type;
>> +    INT32         Len;
>> +
>> +    Node = fdt_next_node (SystemMemoryBase, Prev, NULL);
>> +    if (Node < 0)
>> +      return;
>> +
>> +    Type = fdt_getprop (SystemMemoryBase, Node, "device_type", &Len);
>> +    if (Type && AsciiStrnCmp (Type, "memory", Len) == 0) {
>> +      UINT64 CONST *RegProp;
>> +
>> +      /*
>> +       * Get the 'reg' property of this node. For now, we will assume
>> +       * two 8 byte quantities for base and size, respectively.
>> +       * TODO use #cells root properties instead
>> +       */
>> +      RegProp = fdt_getprop (SystemMemoryBase, Node, "reg", &Len);
>> +      if (RegProp != 0 && Len == (2 * sizeof (UINT64))) {
>> +        UINT64 NewBase, NewSize;
>> +
>> +        NewBase = fdt64_to_cpu (RegProp[0]);
>> +        NewSize = fdt64_to_cpu (RegProp[1]);
>> +
>> +        PcdSet64 (PcdSystemMemoryBase, NewBase);
>> +        PcdSet64 (PcdSystemMemorySize, NewSize);
>> +
>> +        DEBUG ((EFI_D_ERROR, "KVM: System RAM @ 0x%lx - 0x%lx\n",
>> +           NewBase, NewBase + NewSize - 1));
>> +      }
>> +      continue;
>> +    }
>> +  }
>> +}
>
> Too tired to check semantics overly deeply. Prior style remarks apply.
>
> In addition, I think the "continue" is superfluous.
>
>
>> +
>> +EFI_PEI_PPI_DESCRIPTOR      gPlatformPpiTable[] = {
>> +};
>
> GNUism, please avoid. Please spell out
>
> ... gPlatformPpiTable[] = { { 0 } };
>

ok

>> +
>> +VOID
>> +ArmPlatformGetPlatformPpiList (
>> +  OUT UINTN                   *PpiListSize,
>> +  OUT EFI_PEI_PPI_DESCRIPTOR  **PpiList
>> +  )
>> +{
>> +  *PpiListSize = sizeof (gPlatformPpiTable);
>> +  *PpiList = gPlatformPpiTable;
>> +}
>
> [snip KVMHelper.S]
>
>> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMMem.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMMem.c
>> new file mode 100644
>> index 000000000000..55dcf31a5666
>> --- /dev/null
>> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMMem.c
>> @@ -0,0 +1,106 @@
>> +/** @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/ArmPlatformLib.h>
>> +#include <Library/DebugLib.h>
>> +#include <Library/PcdLib.h>
>> +#include <Library/IoLib.h>
>> +#include <Library/MemoryAllocationLib.h>
>> +#include <Library/ArmPlatformGlobalVariableLib.h>
>> +#include <ArmPlatform.h>
>> +
>> +// Number of Virtual Memory Map Descriptors without a Logic Tile
>> +#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS          4
>> +
>> +// 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;
>> +  ARM_MEMORY_REGION_DESCRIPTOR  *VirtualMemoryTable;
>> +  EFI_PHYSICAL_ADDRESS          PhysAddrTop;
>> +
>> +  static INT16 const PARange[] = { 32, 36, 40, 42, 44, 48, -1, -1 };
>> +
>> +  ASSERT (VirtualMemoryMap != NULL);
>> +
>> +  /*
>> +   * Get the max phys address from the CPU config registers
>> +   */
>> +  asm ("mrs  %0, id_aa64mmfr0_el1" : "=r" (PhysAddrTop));
>
> This should be moved into a dedicated helper function / assembly
> language file.
>

ok

>> +  PhysAddrTop = 1ULL << PARange[PhysAddrTop & 7];
>> +  ASSERT (PhysAddrTop != 0);
>> +
>> +  VirtualMemoryTable = AllocatePages (EFI_SIZE_TO_PAGES (
>> +                                     sizeof (ARM_MEMORY_REGION_DESCRIPTOR)
>> +                                     * MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS));
>> +  if (VirtualMemoryTable == NULL) {
>> +       DEBUG ((EFI_D_ERROR, "ArmPlatformGetVirtualMemoryMap: Error: Failed AllocatePages()\n"));
>> +      return;
>> +  }
>> +
>> +  if (FeaturePcdGet (PcdCacheEnable) == TRUE) {
>> +      CacheAttributes = DDR_ATTRIBUTES_CACHED;
>> +  } else {
>> +      CacheAttributes = DDR_ATTRIBUTES_UNCACHED;
>> +  }
>> +
>> +  // System DRAM
>> +  VirtualMemoryTable[0].PhysicalBase = PcdGet64 (PcdSystemMemoryBase);
>> +  VirtualMemoryTable[0].VirtualBase  = VirtualMemoryTable[0].PhysicalBase;
>> +  VirtualMemoryTable[0].Length       = PcdGet64 (PcdSystemMemorySize);
>> +  VirtualMemoryTable[0].Attributes   = CacheAttributes;
>> +
>> +  DEBUG ((EFI_D_ERROR, "ArmPlatformGetVirtualMemoryMap: Dumping DDR Memory Map:\n \
>> +               DDR PhysicalBase: 0x%lX\n \
>> +               VirtualBase: 0x%lX\n \
>> +               Length: 0x%lX\n",
>> +               VirtualMemoryTable[0].PhysicalBase,
>> +               VirtualMemoryTable[0].VirtualBase,
>> +               VirtualMemoryTable[0].Length));
>> +
>> +  // Peripheral space before DRAM
>> +  VirtualMemoryTable[1].PhysicalBase = 0x0;
>> +  VirtualMemoryTable[1].VirtualBase  = 0x0;
>> +  VirtualMemoryTable[1].Length       = VirtualMemoryTable[0].PhysicalBase;
>> +  VirtualMemoryTable[1].Attributes   = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
>> +
>> +  // Peripheral space after DRAM
>> +  VirtualMemoryTable[2].PhysicalBase = VirtualMemoryTable[0].Length + VirtualMemoryTable[1].Length;
>> +  VirtualMemoryTable[2].VirtualBase  = VirtualMemoryTable[2].PhysicalBase;
>> +  VirtualMemoryTable[2].Length       = PhysAddrTop - VirtualMemoryTable[2].PhysicalBase;
>> +  VirtualMemoryTable[2].Attributes   = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
>> +
>> +  // End of Table
>> +  VirtualMemoryTable[3] = (ARM_MEMORY_REGION_DESCRIPTOR){};
>> +
>> +  *VirtualMemoryMap = VirtualMemoryTable;
>> +}
>
> No comments as to validity, but style observations apply. In particular,
> kill those line-trailing backslashes, please; it's "perfectly possible "
> "to " "concatenate string " "literals".
>
> [snip]
>

I know, sorry about that.

>> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.c
>> new file mode 100644
>> index 000000000000..e5edbc407b56
>> --- /dev/null
>> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.c
>> @@ -0,0 +1,96 @@
>> +/** @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>
>> +
>> +  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/BaseLib.h>
>> +#include <Library/DebugLib.h>
>> +#include <Library/EfiResetSystemLib.h>
>> +
>> +#include <ArmPlatform.h>
>> +
>> +/**
>> +  Resets the entire platform.
>> +
>> +  @param  ResetType             The type of reset to perform.
>> +  @param  ResetStatus           The status code for the reset.
>> +  @param  DataSize              The size, in bytes, of WatchdogData.
>> +  @param  ResetData             For a ResetType of EfiResetCold, EfiResetWarm, or
>> +                                EfiResetShutdown the data buffer starts with a Null-terminated
>> +                                Unicode string, optionally followed by additional binary data.
>> +
>> +**/
>> +EFI_STATUS
>> +EFIAPI
>> +LibResetSystem (
>> +  IN EFI_RESET_TYPE   ResetType,
>> +  IN EFI_STATUS       ResetStatus,
>> +  IN UINTN            DataSize,
>> +  IN CHAR16           *ResetData OPTIONAL
>> +  )
>> +{
>> +  register UINTN Rx asm ("x0");
>> +
>> +  switch (ResetType) {
>> +
>> +  case EfiResetPlatformSpecific:
>> +    // Map the platform specific reset as reboot
>> +  case EfiResetWarm:
>> +    // Map a warm reset into a cold reset
>> +  case EfiResetCold:
>> +    // Send a PSCI 0.2 SYSTEM_RESET command
>> +    Rx = PSCI_0_2_FN_SYSTEM_RESET;
>> +    break;
>> +  case EfiResetShutdown:
>> +    // Send a PSCI 0.2 SYSTEM_OFF command
>> +    Rx = PSCI_0_2_FN_SYSTEM_OFF;
>> +    break;
>> +
>> +  default:
>> +    ASSERT (FALSE);
>> +    return EFI_UNSUPPORTED;
>> +  }
>> +
>> +  /*
>> +   * Being a virtualized platform, we are allowed to assume that we
>> +   * are running at EL1, so HVC is appropriate for making PSCI calls.
>> +   */
>> +  asm ("hvc #0" :: "r" (Rx));
>
> Should be a separate... etc etc
>
>> +
>> +  // We should never be here
>> +  while (1);
>> +}
>
> CpuDeadLoop() is more idiomatic in edk2.
>
>> +
>> +/**
>> +  Initialize any infrastructure required for LibResetSystem () to function.
>> +
>> +  @param  ImageHandle   The firmware allocated handle for the EFI image.
>> +  @param  SystemTable   A pointer to the EFI System Table.
>> +
>> +  @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.
>> +
>> +**/
>> +EFI_STATUS
>> +EFIAPI
>> +LibInitializeResetSystem (
>> +  IN EFI_HANDLE        ImageHandle,
>> +  IN EFI_SYSTEM_TABLE  *SystemTable
>> +  )
>> +{
>> +  return EFI_SUCCESS;
>> +}
>

Thanks again for taking the time.
Laszlo Ersek Aug. 27, 2014, 11:21 a.m. UTC | #3
On 08/27/14 10:27, Ard Biesheuvel wrote:
> On 27 August 2014 01:36, Laszlo Ersek <lersek@redhat.com> wrote:
>> On 08/26/14 15:03, Ard Biesheuvel wrote:

>>> +#pragma pack (1)
>>> +typedef struct {
>>> +  VENDOR_DEVICE_PATH                  Vendor;
>>> +  UINT32                              Instance;
>>> +  EFI_DEVICE_PATH_PROTOCOL            End;
>>> +} VIRTIO_BLK_DEVICE_PATH;
>>> +#pragma pack ()
>>
>> Ugh. :)
>>
>> Have you seen my earlier patches where the vendor device path node
>> corresponding to a virtio-mmio transport actually included the base
>> address of the MMIO register block? I think such a hwvendor devpath node
>> is much more useful; it can actually help you debug.
>>
> 
> I will just stick a EFI_PHYSICAL_ADDRESS in there instead, or would
> you prefer UINT64?

UINT64 sounds good.

>>> +  FdtImageData = AllocatePages (EFI_SIZE_TO_PAGES (fdt_totalsize (MemoryBase)));
>>
>> What's wrong with AllocatePool()? Does the EFI stub require full pages,
>> and page alignment?
>>
> 
> No, AllocatePool() should be fine.

OK.

Tying back to the other patch's discussion, I've already mentioned
AllocateCopyPool(). It's a nice convenience function that can save you a
separate call to CopyMem().

(Independently, we should be very clear that the
AllocatePages()/AllocatePool() calls discussed here, vs. the one that
you'll add to the platform PEI, are *very* different. They are from the
same MemoryAllocationLib library class, but the library instances in
question are specific to the UEFI phase:

- MdePkg/Library/PeiMemoryAllocationLib/
- MdePkg/Library/UefiMemoryAllocationLib/

The former is ultimately backed by HOB creation, while the latter is
backed by a UEFI boot service.

So, you'll remove this DTB relocation from DXE completely, and do it in
the platform PEIM instead (either with in-place coverage, or real
relocation to permanent PEI RAM, with AllocateCopyPool()).)

> I will check the logic carefully. What should happen is that the
> traversal of the device tree should proceed, so other peripherals are
> detected and installed even if the virtio transports are not.

Sounds great. Actually, I think we should keep whatever virtio-mmio
transports we managed to install as well; it's not like there's some
inter-dependency between virtio devices. Whatever works is likely useful
in isolation too.

>>> +      break;
>>> +
>>> +    case GIC:
>>> +      ASSERT (Len == 32);
>>> +
>>> +      DistBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);
>>> +      CpuBase = fdt64_to_cpu (((UINT64 *)RegProp)[2]);
>>> +      PcdSet32 (PcdGicDistributorBase, DistBase);
>>> +      PcdSet32 (PcdGicInterruptInterfaceBase, CpuBase);
>>
>> DistBase and CpuBase are UINT32s, matching the PCDs, but they don't
>> match the FDT (UINT64). Is that okay?
>>
> 
> Well, it is highly unlikely that peripherals like GIC would be moved
> beyond 4 GB in the physical address space, and the device tree just
> uses 64-bit addresses in this instantiation, so for now, I think this
> is fine. Otherwise, we should update the GIC driver to use UINT64
> instead.

Alright. Please either add an assert, or just a small comment, for the
uninitiated like me :)

[snip]

Thanks
Laszlo

------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
diff mbox

Patch

diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization-KVM.dsc b/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization-KVM.dsc
new file mode 100644
index 000000000000..e0817fca927e
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization-KVM.dsc
@@ -0,0 +1,223 @@ 
+#
+#  Copyright (c) 2011-2013, 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 Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+  PLATFORM_NAME                  = AArch64Virtualization-KVM
+  PLATFORM_GUID                  = 37d7e986-f7e9-45c2-8067-e371421a626c
+  PLATFORM_VERSION               = 0.1
+  DSC_SPECIFICATION              = 0x00010005
+  OUTPUT_DIRECTORY               = Build/AArch64Virtualization-KVM
+  SUPPORTED_ARCHITECTURES        = AARCH64
+  BUILD_TARGETS                  = DEBUG|RELEASE
+  SKUID_IDENTIFIER               = DEFAULT
+  FLASH_DEFINITION               = ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization-KVM.fdf
+
+!include ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization.dsc.inc
+
+[LibraryClasses.common]
+  ArmLib|ArmPkg/Library/ArmLib/AArch64/AArch64Lib.inf
+  ArmCpuLib|ArmPkg/Drivers/ArmCpuLib/ArmCortexAEMv8Lib/ArmCortexAEMv8Lib.inf
+  ArmPlatformLib|ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/AArch64KVMLib.inf
+
+  # Virtio Support
+  VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
+  VirtioMmioDeviceLib|OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf
+
+  ArmPlatformSysConfigLib|ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationSysConfigLibKVM/AArch64VirtualizationSysConfigLibKVM.inf
+
+  TimerLib|ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf
+
+[LibraryClasses.common.SEC]
+  ArmLib|ArmPkg/Library/ArmLib/AArch64/AArch64LibSec.inf
+
+[BuildOptions]
+  GCC:*_*_AARCH64_PLATFORM_FLAGS == -I$(WORKSPACE)/ArmPlatformPkg/AArch64VirtualizationPkg/Include -I$(WORKSPACE)/ArmPlatformPkg/AArch64VirtualizationPkg/Include/Platform/KVM
+
+
+################################################################################
+#
+# Pcd Section - list of all EDK II PCD Entries defined by this Platform
+#
+################################################################################
+
+[PcdsFeatureFlag.common]
+
+  ## If TRUE, Graphics Output Protocol will be installed on virtual handle created by ConsplitterDxe.
+  #  It could be set FALSE to save size.
+  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|FALSE
+
+  gArmTokenSpaceGuid.PcdArmArchTimerUseVirtual|TRUE
+
+[PcdsFixedAtBuild.common]
+  #gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80
+
+  gArmPlatformTokenSpaceGuid.PcdFirmwareVendor|"KVM"
+  gEmbeddedTokenSpaceGuid.PcdEmbeddedPrompt|"KVM"
+
+  gArmPlatformTokenSpaceGuid.PcdCoreCount|1
+  gArmTokenSpaceGuid.PcdVFPEnabled|1
+
+  gArmPlatformTokenSpaceGuid.PcdCPUCoresStackBase|0x4007c000
+  gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize|0x4000
+
+  # Size of the region used by UEFI in permanent memory (Reserved 64MB)
+  gArmPlatformTokenSpaceGuid.PcdSystemMemoryUefiRegionSize|0x04000000
+
+  gArmPlatformTokenSpaceGuid.PcdPeiGlobalVariableSize|0x20
+
+  #
+  # ARM Pcds
+  #
+  gArmTokenSpaceGuid.PcdArmUncachedMemoryMask|0x0000000040000000
+
+  ## Trustzone enable (to make the transition from EL3 to EL2 in ArmPlatformPkg/Sec)
+  gArmTokenSpaceGuid.PcdTrustzoneSupport|FALSE
+
+  #
+  # ARM PrimeCell
+  #
+
+  ## PL011 - Serial Terminal
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase|0x9000000
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate|38400
+
+  #
+  # ARM OS Loader
+  #
+  # Versatile Express machine type (ARM VERSATILE EXPRESS = 2272) required for ARM Linux:
+  gArmPlatformTokenSpaceGuid.PcdDefaultBootDescription|L"Linux from SemiHosting"
+  gArmPlatformTokenSpaceGuid.PcdDefaultBootDevicePath|L"VenHw(C5B9C74A-6D72-4719-99AB-C59F199091EB)/Image"
+  gArmPlatformTokenSpaceGuid.PcdDefaultBootArgument|"root=/dev/vda2 rw console=ttyAMA0 earlyprintk=pl011,0x1c090000 maxcpus=4 debug user_debug=31 loglevel=9"
+  gArmPlatformTokenSpaceGuid.PcdDefaultBootType|2
+  gArmPlatformTokenSpaceGuid.PcdFdtDevicePath|L"VenHw(C5B9C74A-6D72-4719-99AB-C59F199091EB)/foundation-v8.dtb"
+
+  # Use the serial console (ConIn & ConOut) and the Graphic driver (ConOut)
+  gArmPlatformTokenSpaceGuid.PcdDefaultConOutPaths|L"VenHw(D3987D4B-971A-435F-8CAF-4967EB627241)/Uart(38400,8,N,1)/VenPcAnsi();"
+  gArmPlatformTokenSpaceGuid.PcdDefaultConInPaths|L"VenHw(D3987D4B-971A-435F-8CAF-4967EB627241)/Uart(38400,8,N,1)/VenPcAnsi()"
+  gArmPlatformTokenSpaceGuid.PcdPlatformBootTimeOut|10  
+
+  #
+  # ARM Virtual Architectural Timer
+  #
+  gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz|100000000
+
+[PcdsDynamicDefault.common]
+  # System Memory -- 1 MB initially, actual size will be fetched from DT
+  gArmTokenSpaceGuid.PcdSystemMemoryBase|0x40000000
+  gArmTokenSpaceGuid.PcdSystemMemorySize|0x00100000
+
+  gArmTokenSpaceGuid.PcdArmArchTimerSecIntrNum|0x0
+  gArmTokenSpaceGuid.PcdArmArchTimerIntrNum|0x0
+  gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum|0x0
+  gArmTokenSpaceGuid.PcdArmArchTimerHypIntrNum|0x0
+
+  #
+  # ARM General Interrupt Controller
+  #
+  gArmTokenSpaceGuid.PcdGicDistributorBase|0x0
+  gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase|0x0
+
+  ## PL031 RealTimeClock
+  gArmPlatformTokenSpaceGuid.PcdPL031RtcBase|0x0
+  
+################################################################################
+#
+# Components Section - list of all EDK II Modules needed by this Platform
+#
+################################################################################
+[Components.common]
+
+  #
+  # PEI Phase modules
+  #
+  ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf {
+    <LibraryClasses>
+      ArmPlatformGlobalVariableLib|ArmPlatformPkg/Library/ArmPlatformGlobalVariableLib/Pei/PeiArmPlatformGlobalVariableLib.inf
+  }
+  MdeModulePkg/Core/Pei/PeiMain.inf
+  MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+  ArmPlatformPkg/PlatformPei/PlatformPeim.inf
+  ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.inf
+  ArmPkg/Drivers/CpuPei/CpuPei.inf
+  IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.inf
+  Nt32Pkg/BootModePei/BootModePei.inf
+  MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
+  MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf {
+    <LibraryClasses>
+      NULL|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
+  }
+
+  #
+  # DXE
+  #
+  MdeModulePkg/Core/Dxe/DxeMain.inf {
+    <LibraryClasses>
+      NULL|MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf
+  }
+  MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+
+  #
+  # Architectural Protocols
+  #
+  ArmPkg/Drivers/CpuDxe/CpuDxe.inf
+  MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+  MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
+  MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
+  MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf
+  MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+  MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
+  EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf
+  EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
+  EmbeddedPkg/MetronomeDxe/MetronomeDxe.inf
+
+  MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
+  MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
+  MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
+  MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+  EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf
+  EmbeddedPkg/SerialDxe/SerialDxe.inf
+ 
+  MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+
+  ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
+  ArmPkg/Drivers/TimerDxe/TimerDxe.inf
+  MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+
+  #
+  # Platform Driver
+  #
+  ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdt.inf
+  OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
+  OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
+  OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
+  OvmfPkg/VirtioNetDxe/VirtioNet.inf
+
+
+  #
+  # FAT filesystem + GPT/MBR partitioning
+  #
+  MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
+  MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
+  MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
+
+  #
+  # Bds
+  #
+  MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+  ArmPlatformPkg/Bds/Bds.inf
diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization-KVM.fdf b/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization-KVM.fdf
new file mode 100644
index 000000000000..a5fe6e57a264
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization-KVM.fdf
@@ -0,0 +1,307 @@ 
+#
+#  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.
+#
+
+################################################################################
+#
+# FD Section
+# The [FD] Section is made up of the definition statements and a
+# description of what goes into  the Flash Device Image.  Each FD section
+# defines one flash "device" image.  A flash device image may be one of
+# the following: Removable media bootable image (like a boot floppy
+# image,) an Option ROM image (that would be "flashed" into an add-in
+# card,) a System "Flash"  image (that would be burned into a system's
+# flash) or an Update ("Capsule") image that will be used to update and
+# existing system flash.
+#
+################################################################################
+
+[FD.KVM_EFI]
+BaseAddress   = 0x00000000|gArmTokenSpaceGuid.PcdFdBaseAddress  # KVM assigns 0 - 0x8000000 for a BootROM
+Size          = 0x00200000|gArmTokenSpaceGuid.PcdFdSize         # The size in bytes of the FLASH Device
+ErasePolarity = 1
+
+# This one is tricky, it must be: BlockSize * NumBlocks = Size
+BlockSize     = 0x00001000
+NumBlocks     = 0x200
+
+################################################################################
+#
+# Following are lists of FD Region layout which correspond to the locations of different
+# images within the flash device.
+#
+# Regions must be defined in ascending order and may not overlap.
+#
+# A Layout Region start with a eight digit hex offset (leading "0x" required) followed by
+# the pipe "|" character, followed by the size of the region, also in hex with the leading
+# "0x" characters. Like:
+# Offset|Size
+# PcdOffsetCName|PcdSizeCName
+# RegionType <FV, DATA, or FILE>
+#
+################################################################################
+
+#
+# UEFI has trouble dealing with FVs that reside at physical address 0x0.
+# So instead, but a hardcoded 'jump to 0x1000' at offset 0x0, and put the
+# real FV at offset 0x1000
+#
+0x00000000|0x00001000
+DATA = {
+  0x0, 0x4, 0x0, 0x14   # 'b 0x1000' in AArch64 ASM
+}
+
+0x00001000|0x001ff000
+gArmTokenSpaceGuid.PcdFvBaseAddress|gArmTokenSpaceGuid.PcdFvSize
+FV = FVMAIN_COMPACT
+
+
+################################################################################
+#
+# FV Section
+#
+# [FV] section is used to define what components or modules are placed within a flash
+# device file.  This section also defines order the components and modules are positioned
+# within the image.  The [FV] section consists of define statements, set statements and
+# module statements.
+#
+################################################################################
+
+[FV.FvMain]
+BlockSize          = 0x40
+NumBlocks          = 0         # This FV gets compressed so make it just big enough
+FvAlignment        = 16        # FV alignment and FV attributes setting.
+ERASE_POLARITY     = 1
+MEMORY_MAPPED      = TRUE
+STICKY_WRITE       = TRUE
+LOCK_CAP           = TRUE
+LOCK_STATUS        = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP  = TRUE
+WRITE_STATUS       = TRUE
+WRITE_LOCK_CAP     = TRUE
+WRITE_LOCK_STATUS  = TRUE
+READ_DISABLED_CAP  = TRUE
+READ_ENABLED_CAP   = TRUE
+READ_STATUS        = TRUE
+READ_LOCK_CAP      = TRUE
+READ_LOCK_STATUS   = TRUE
+
+  APRIORI DXE {
+    INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+  }
+  INF MdeModulePkg/Core/Dxe/DxeMain.inf
+  INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+  INF ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdt.inf
+
+  #
+  # PI DXE Drivers producing Architectural Protocols (EFI Services)
+  #
+  INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf
+  INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+  INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
+  INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
+  INF MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf
+  INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+  INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
+  INF EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf
+  INF EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
+  INF EmbeddedPkg/MetronomeDxe/MetronomeDxe.inf
+  INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+
+  #
+  # Multiple Console IO support
+  #
+  INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
+  INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
+  INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
+  INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+  INF EmbeddedPkg/SerialDxe/SerialDxe.inf
+
+  INF ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
+  INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf
+  INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+
+  #
+  # FAT filesystem + GPT/MBR partitioning
+  #
+  INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
+  INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
+  INF FatBinPkg/EnhancedFatDxe/Fat.inf
+  INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
+
+  #
+  # Platform Driver
+  #
+  INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
+  INF OvmfPkg/VirtioNetDxe/VirtioNet.inf
+  INF OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
+  INF OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
+
+  #
+  # UEFI application (Shell Embedded Boot Loader)
+  #
+  INF ShellBinPkg/UefiShell/UefiShell.inf
+
+  #
+  # Bds
+  #
+  INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+  INF ArmPlatformPkg/Bds/Bds.inf
+
+
+[FV.FVMAIN_COMPACT]
+FvAlignment        = 16
+ERASE_POLARITY     = 1
+MEMORY_MAPPED      = TRUE
+STICKY_WRITE       = TRUE
+LOCK_CAP           = TRUE
+LOCK_STATUS        = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP  = TRUE
+WRITE_STATUS       = TRUE
+WRITE_LOCK_CAP     = TRUE
+WRITE_LOCK_STATUS  = TRUE
+READ_DISABLED_CAP  = TRUE
+READ_ENABLED_CAP   = TRUE
+READ_STATUS        = TRUE
+READ_LOCK_CAP      = TRUE
+READ_LOCK_STATUS   = TRUE
+
+  APRIORI PEI {
+    INF  MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+  }
+  INF ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf
+  INF MdeModulePkg/Core/Pei/PeiMain.inf
+  INF ArmPlatformPkg/PlatformPei/PlatformPeim.inf
+  INF ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.inf
+  INF ArmPkg/Drivers/CpuPei/CpuPei.inf
+  INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+  INF IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.inf
+  INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+
+  FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
+    SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE {
+      SECTION FV_IMAGE = FVMAIN
+    }
+  }
+
+
+################################################################################
+#
+# Rules are use with the [FV] section's module INF type to define
+# how an FFS file is created for a given INF file. The following Rule are the default
+# rules for the different module type. User can add the customized rules to define the
+# content of the FFS file.
+#
+################################################################################
+
+
+############################################################################
+# Example of a DXE_DRIVER FFS file with a Checksum encapsulation section   #
+############################################################################
+#
+#[Rule.Common.DXE_DRIVER]
+#  FILE DRIVER = $(NAMED_GUID) {
+#    DXE_DEPEX    DXE_DEPEX               Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+#    COMPRESS PI_STD {
+#      GUIDED {
+#        PE32     PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi
+#        UI       STRING="$(MODULE_NAME)" Optional
+#        VERSION  STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+#      }
+#    }
+#  }
+#
+############################################################################
+
+[Rule.Common.SEC]
+  FILE SEC = $(NAMED_GUID) RELOCS_STRIPPED {
+    TE  TE Align = 128                  $(INF_OUTPUT)/$(MODULE_NAME).efi
+  }
+
+[Rule.Common.PEI_CORE]
+  FILE PEI_CORE = $(NAMED_GUID) {
+    TE     TE Align = 8                 $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI     STRING ="$(MODULE_NAME)" Optional
+  }
+
+[Rule.Common.PEIM]
+  FILE PEIM = $(NAMED_GUID) {
+     PEI_DEPEX PEI_DEPEX Optional       $(INF_OUTPUT)/$(MODULE_NAME).depex
+     TE       TE Align = 8              $(INF_OUTPUT)/$(MODULE_NAME).efi
+     UI       STRING="$(MODULE_NAME)" Optional
+  }
+
+[Rule.Common.PEIM.TIANOCOMPRESSED]
+  FILE PEIM = $(NAMED_GUID) DEBUG_MYTOOLS_IA32 {
+    PEI_DEPEX PEI_DEPEX Optional        $(INF_OUTPUT)/$(MODULE_NAME).depex
+    GUIDED A31280AD-481E-41B6-95E8-127F4C984779 PROCESSING_REQUIRED = TRUE {
+      PE32      PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi
+      UI        STRING="$(MODULE_NAME)" Optional
+    }
+  }
+
+[Rule.Common.DXE_CORE]
+  FILE DXE_CORE = $(NAMED_GUID) {
+    PE32     PE32                       $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI       STRING="$(MODULE_NAME)" Optional
+  }
+
+[Rule.Common.UEFI_DRIVER]
+  FILE DRIVER = $(NAMED_GUID) {
+    DXE_DEPEX    DXE_DEPEX              Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+    PE32         PE32                   $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI           STRING="$(MODULE_NAME)" Optional
+  }
+
+[Rule.Common.DXE_DRIVER]
+  FILE DRIVER = $(NAMED_GUID) {
+    DXE_DEPEX    DXE_DEPEX              Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+    PE32         PE32                   $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI           STRING="$(MODULE_NAME)" Optional
+  }
+
+[Rule.Common.DXE_RUNTIME_DRIVER]
+  FILE DRIVER = $(NAMED_GUID) {
+    DXE_DEPEX    DXE_DEPEX              Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+    PE32         PE32                   $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI           STRING="$(MODULE_NAME)" Optional
+  }
+
+[Rule.Common.UEFI_APPLICATION]
+  FILE APPLICATION = $(NAMED_GUID) {
+    UI     STRING ="$(MODULE_NAME)"     Optional
+    PE32   PE32                         $(INF_OUTPUT)/$(MODULE_NAME).efi
+  }
+
+[Rule.Common.UEFI_DRIVER.BINARY]
+  FILE DRIVER = $(NAMED_GUID) {
+    DXE_DEPEX DXE_DEPEX Optional      |.depex
+    PE32      PE32                    |.efi
+    UI        STRING="$(MODULE_NAME)" Optional
+    VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
+
+[Rule.Common.UEFI_APPLICATION.BINARY]
+  FILE APPLICATION = $(NAMED_GUID) {
+    PE32      PE32                    |.efi
+    UI        STRING="$(MODULE_NAME)" Optional
+    VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
+
+[Rule.Common.USER_DEFINED.ACPITABLE]
+  FILE FREEFORM = $(NAMED_GUID) {
+    RAW       ACPI                    |.acpi
+    RAW       ASL                     |.aml
+    UI        STRING="$(MODULE_NAME)" Optional
+  }
+
diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization.dsc.inc b/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization.dsc.inc
new file mode 100644
index 000000000000..65fadfe694be
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization.dsc.inc
@@ -0,0 +1,354 @@ 
+#
+#  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.             
+#
+#
+
+[LibraryClasses.common]
+!if $(TARGET) == RELEASE
+  DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+  UncachedMemoryAllocationLib|ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf
+!else
+  DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+  UncachedMemoryAllocationLib|ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf
+#  UncachedMemoryAllocationLib|ArmPkg/Library/DebugUncachedMemoryAllocationLib/DebugUncachedMemoryAllocationLib.inf
+!endif
+  DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+  
+  BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+  SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
+  PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
+  PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+  UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
+  CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
+
+  UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
+  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+  UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
+  DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+  UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+  DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
+  UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+  UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
+  HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
+  UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf  
+
+  UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
+
+  #
+  # Allow dynamic PCDs
+  #
+  PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+  
+  # 1/123 faster than Stm or Vstm version
+  #BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
+  BaseMemoryLib|ArmPkg/Library/BaseMemoryLibStm/BaseMemoryLibStm.inf
+
+  # Networking Requirements
+  NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf
+  DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf
+  UdpIoLib|MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf
+  IpIoLib|MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.inf
+
+  # ARM Architectural Libraries
+  CacheMaintenanceLib|ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf
+  DefaultExceptionHandlerLib|ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf
+  CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf
+  ArmDisassemblerLib|ArmPkg/Library/ArmDisassemblerLib/ArmDisassemblerLib.inf
+  DmaLib|ArmPkg/Library/ArmDmaLib/ArmDmaLib.inf
+  ArmGicLib|ArmPkg/Drivers/ArmGic/ArmGicLib.inf
+  ArmPlatformStackLib|ArmPlatformPkg/Library/ArmPlatformStackLib/ArmPlatformStackLib.inf
+  ArmSmcLib|ArmPkg/Library/ArmSmcLib/ArmSmcLib.inf
+
+  EfiResetSystemLib|ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.inf
+
+  # ARM PL111 Lcd Driver
+  LcdPlatformLib|ArmPlatformPkg/ArmVExpressPkg/Library/PL111LcdArmVExpressLib/PL111LcdArmVExpressLib.inf
+  # ARM PL031 RTC Driver
+  RealTimeClockLib|ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.inf
+  # ARM PL354 SMC Driver
+  PL35xSmcLib|ArmPlatformPkg/Drivers/PL35xSmc/PL35xSmc.inf
+  # ARM PL011 UART Driver
+  PL011UartLib|ArmPlatformPkg/Drivers/PL011Uart/PL011Uart.inf
+  SerialPortLib|ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortLib.inf
+  SerialPortExtLib|ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortExtLib.inf
+  # ARM SP804 Dual Timer Driver
+  #TimerLib|ArmPlatformPkg/Library/SP804TimerLib/SP804TimerLib.inf
+
+  # EBL Related Libraries  
+  EblCmdLib|ArmPlatformPkg/Library/EblCmdLib/EblCmdLib.inf
+  EfiFileLib|EmbeddedPkg/Library/EfiFileLib/EfiFileLib.inf
+  EblAddExternalCommandLib|EmbeddedPkg/Library/EblAddExternalCommandLib/EblAddExternalCommandLib.inf
+  EblNetworkLib|EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.inf
+  
+  #
+  # Uncomment (and comment out the next line) For RealView Debugger. The Standard IO window 
+  # in the debugger will show load and unload commands for symbols. You can cut and paste this
+  # into the command window to load symbols. We should be able to use a script to do this, but
+  # the version of RVD I have does not support scripts accessing system memory.
+  #
+  #PeCoffExtraActionLib|ArmPkg/Library/RvdPeCoffExtraActionLib/RvdPeCoffExtraActionLib.inf
+  PeCoffExtraActionLib|ArmPkg/Library/DebugPeCoffExtraActionLib/DebugPeCoffExtraActionLib.inf
+  #PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+    
+  DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
+  DebugAgentTimerLib|EmbeddedPkg/Library/DebugAgentTimerLibNull/DebugAgentTimerLibNull.inf
+
+  #SemihostLib|ArmPkg/Library/SemihostLib/SemihostLib.inf  
+
+  # BDS Libraries
+  BdsLib|ArmPkg/Library/BdsLib/BdsLib.inf
+  FdtLib|EmbeddedPkg/Library/FdtLib/FdtLib.inf
+
+[LibraryClasses.common.SEC]
+  PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+  ArmPlatformSecExtraActionLib|ArmPlatformPkg/Library/DebugSecExtraActionLib/DebugSecExtraActionLib.inf
+  ArmPlatformGlobalVariableLib|ArmPlatformPkg/Library/ArmPlatformGlobalVariableLib/Sec/SecArmPlatformGlobalVariableLib.inf
+  
+  DebugAgentLib|ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentSymbolsBaseLib.inf
+  DefaultExceptionHandlerLib|ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLibBase.inf
+  
+[LibraryClasses.common.PEI_CORE]
+  #PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+  PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+  PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+  MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+  PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
+  PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf
+  ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+  OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+  UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
+  ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
+  
+  ArmPlatformGlobalVariableLib|ArmPlatformPkg/Library/ArmPlatformGlobalVariableLib/Pei/PeiArmPlatformGlobalVariableLib.inf
+  PeiServicesTablePointerLib|ArmPlatformPkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
+  
+[LibraryClasses.common.PEIM]
+  #PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+  PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+  PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+  MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+  PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
+  PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf
+  ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+  OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+  PeiResourcePublicationLib|MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf
+  UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
+  ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
+
+  ArmPlatformGlobalVariableLib|ArmPlatformPkg/Library/ArmPlatformGlobalVariableLib/Pei/PeiArmPlatformGlobalVariableLib.inf
+  PeiServicesTablePointerLib|ArmPlatformPkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
+
+[LibraryClasses.common.DXE_CORE]
+  HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
+  MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
+  DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
+  ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
+  ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
+  UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
+  DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
+  PerformanceLib|MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf
+
+[LibraryClasses.common.DXE_DRIVER]
+  ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
+  DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
+  SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
+  PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf
+  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+  ArmPlatformGlobalVariableLib|ArmPlatformPkg/Library/ArmPlatformGlobalVariableLib/Dxe/DxeArmPlatformGlobalVariableLib.inf
+
+[LibraryClasses.common.UEFI_APPLICATION]
+  UefiDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf
+  PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf
+  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+  HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
+
+[LibraryClasses.common.UEFI_DRIVER]
+  ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
+  UefiDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf
+  ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
+  PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf
+  DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
+  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+
+[LibraryClasses.common.DXE_RUNTIME_DRIVER]
+  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+  ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
+
+[LibraryClasses.ARM]
+  #
+  # It is not possible to prevent the ARM compiler for generic intrinsic functions.
+  # This library provides the instrinsic functions generate by a given compiler.
+  # [LibraryClasses.ARM] and NULL mean link this library into all ARM images.
+  #
+  NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
+
+[LibraryClasses.AARCH64]
+  NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
+
+
+[BuildOptions]
+  RVCT:RELEASE_*_*_CC_FLAGS  = -DMDEPKG_NDEBUG
+
+  GCC:RELEASE_*_*_CC_FLAGS  = -DMDEPKG_NDEBUG
+
+################################################################################
+#
+# Pcd Section - list of all EDK II PCD Entries defined by this Platform
+#
+################################################################################
+
+[PcdsFeatureFlag.common]
+  gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable|TRUE
+  gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable|TRUE
+  gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable|TRUE
+  gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable|TRUE
+  
+  #
+  # Control what commands are supported from the UI
+  # Turn these on and off to add features or save size
+  #  
+  gEmbeddedTokenSpaceGuid.PcdEmbeddedMacBoot|TRUE
+  gEmbeddedTokenSpaceGuid.PcdEmbeddedDirCmd|TRUE
+  gEmbeddedTokenSpaceGuid.PcdEmbeddedHobCmd|TRUE
+  gEmbeddedTokenSpaceGuid.PcdEmbeddedHwDebugCmd|TRUE
+  gEmbeddedTokenSpaceGuid.PcdEmbeddedPciDebugCmd|TRUE
+  gEmbeddedTokenSpaceGuid.PcdEmbeddedIoEnable|FALSE
+  gEmbeddedTokenSpaceGuid.PcdEmbeddedScriptCmd|FALSE
+
+  gEmbeddedTokenSpaceGuid.PcdCacheEnable|TRUE
+  
+  # Use the Vector Table location in CpuDxe. We will not copy the Vector Table at PcdCpuVectorBaseAddress
+  gArmTokenSpaceGuid.PcdRelocateVectorTable|FALSE
+  
+  gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob|TRUE
+  
+  gEfiMdeModulePkgTokenSpaceGuid.PcdTurnOffUsbLegacySupport|TRUE
+
+[PcdsFixedAtBuild.common]
+  gArmPlatformTokenSpaceGuid.PcdFirmwareVendor|"ARM Versatile Express"
+  
+  gEmbeddedTokenSpaceGuid.PcdEmbeddedPrompt|"VExpress"
+  gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength|1000000
+  gEfiMdePkgTokenSpaceGuid.PcdMaximumAsciiStringLength|1000000
+  gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength|1000000
+  gEfiMdePkgTokenSpaceGuid.PcdSpinLockTimeout|10000000
+  gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue|0xAF
+  gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|1
+  gEfiMdePkgTokenSpaceGuid.PcdPostCodePropertyMask|0
+  gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|320
+
+  # DEBUG_ASSERT_ENABLED       0x01
+  # DEBUG_PRINT_ENABLED        0x02
+  # DEBUG_CODE_ENABLED         0x04
+  # CLEAR_MEMORY_ENABLED       0x08
+  # ASSERT_BREAKPOINT_ENABLED  0x10
+  # ASSERT_DEADLOOP_ENABLED    0x20
+!if $(TARGET) == RELEASE
+  gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x21
+!else
+  gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2f
+!endif
+
+  #  DEBUG_INIT      0x00000001  // Initialization
+  #  DEBUG_WARN      0x00000002  // Warnings
+  #  DEBUG_LOAD      0x00000004  // Load events
+  #  DEBUG_FS        0x00000008  // EFI File system
+  #  DEBUG_POOL      0x00000010  // Alloc & Free's
+  #  DEBUG_PAGE      0x00000020  // Alloc & Free's
+  #  DEBUG_INFO      0x00000040  // Verbose
+  #  DEBUG_DISPATCH  0x00000080  // PEI/DXE Dispatchers
+  #  DEBUG_VARIABLE  0x00000100  // Variable
+  #  DEBUG_BM        0x00000400  // Boot Manager
+  #  DEBUG_BLKIO     0x00001000  // BlkIo Driver
+  #  DEBUG_NET       0x00004000  // SNI Driver
+  #  DEBUG_UNDI      0x00010000  // UNDI Driver
+  #  DEBUG_LOADFILE  0x00020000  // UNDI Driver
+  #  DEBUG_EVENT     0x00080000  // Event messages
+  #  DEBUG_GCD       0x00100000  // Global Coherency Database changes
+  #  DEBUG_CACHE     0x00200000  // Memory range cachability changes
+  #  DEBUG_ERROR     0x80000000  // Error
+  gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000000F
+
+  gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07
+
+  gEmbeddedTokenSpaceGuid.PcdEmbeddedAutomaticBootCommand|""
+  gEmbeddedTokenSpaceGuid.PcdEmbeddedDefaultTextColor|0x07
+  gEmbeddedTokenSpaceGuid.PcdEmbeddedMemVariableStoreSize|0x10000
+  
+  #
+  # Optional feature to help prevent EFI memory map fragments
+  # Turned on and off via: PcdPrePiProduceMemoryTypeInformationHob
+  # Values are in EFI Pages (4K). DXE Core will make sure that 
+  # at least this much of each type of memory can be allocated 
+  # from a single memory range. This way you only end up with
+  # maximum of two fragements for each type in the memory map
+  # (the memory used, and the free memory that was prereserved
+  # but not used).
+  #
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory|0
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS|0
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType|0
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData|50
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode|20
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode|400
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData|20000
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode|20
+  gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData|0
+    
+  #
+  # ARM Pcds
+  #
+  gArmTokenSpaceGuid.PcdArmUncachedMemoryMask|0x0000000000000000
+  
+  #
+  # ARM PrimeCell
+  #
+
+  #
+  # ARM OS Loader
+  #
+  # Versatile Express machine type (ARM VERSATILE EXPRESS = 2272) required for ARM Linux: 
+  gArmTokenSpaceGuid.PcdArmMachineType|2272
+  gArmPlatformTokenSpaceGuid.PcdDefaultBootDescription|L"Linux from NorFlash"
+  gArmPlatformTokenSpaceGuid.PcdDefaultBootDevicePath|L"VenHw(E7223039-5836-41E1-B542-D7EC736C5E59)/MemoryMapped(0x0,0xED000000,0xED400000)"
+  gArmPlatformTokenSpaceGuid.PcdDefaultBootArgument|""
+  gArmPlatformTokenSpaceGuid.PcdDefaultBootType|1
+  
+  # Use the serial console (ConIn & ConOut) and the Graphic driver (ConOut)
+  gArmPlatformTokenSpaceGuid.PcdDefaultConOutPaths|L"VenHw(D3987D4B-971A-435F-8CAF-4967EB627241)/Uart(38400,8,N,1)/VenPcAnsi();VenHw(CE660500-824D-11E0-AC72-0002A5D5C51B)"
+  gArmPlatformTokenSpaceGuid.PcdDefaultConInPaths|L"VenHw(D3987D4B-971A-435F-8CAF-4967EB627241)/Uart(38400,8,N,1)/VenPcAnsi()"
+  gArmPlatformTokenSpaceGuid.PcdPlatformBootTimeOut|10
+
+[Components.common]
+  #
+  # Networking stack
+  #
+  MdeModulePkg/Universal/Network/DpcDxe/DpcDxe.inf
+  MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf
+  MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.inf
+  MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf
+  MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.inf
+  MdeModulePkg/Universal/Network/MnpDxe/MnpDxe.inf
+  MdeModulePkg/Universal/Network/VlanConfigDxe/VlanConfigDxe.inf
+  MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Dxe.inf
+  MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dxe.inf
+  MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Dxe.inf
+  MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf
+  MdeModulePkg/Universal/Network/IScsiDxe/IScsiDxe.inf
diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdt.inf b/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdt.inf
new file mode 100644
index 000000000000..fa1057202024
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdt.inf
@@ -0,0 +1,60 @@ 
+## @file
+#  Device tree enumeration DXE driver for AArch64 VMs
+#
+#  Copyright (c) 2014, 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                      = VirtFdt
+  FILE_GUID                      = 837DCA9E-E874-4D82-B29A-23FE0E23D1E2
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+
+  ENTRY_POINT                    = InitializeVirtFdtDxe
+
+[Sources]
+  VirtFdtDxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  UefiDriverEntryPoint
+  DxeServicesLib
+  FdtLib
+  VirtioMmioDeviceLib
+
+[Guids]
+  gFdtTableGuid
+
+[FeaturePcd]
+
+[Pcd]
+  gArmTokenSpaceGuid.PcdSystemMemoryBase
+  gArmTokenSpaceGuid.PcdGicDistributorBase
+  gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
+  gArmTokenSpaceGuid.PcdArmArchTimerSecIntrNum
+  gArmTokenSpaceGuid.PcdArmArchTimerIntrNum
+  gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum
+  gArmTokenSpaceGuid.PcdArmArchTimerHypIntrNum
+  gArmPlatformTokenSpaceGuid.PcdPL031RtcBase
+
+[Protocols]
+
+[Depex]
+  TRUE
diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdtDxe.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdtDxe.c
new file mode 100644
index 000000000000..04840e5d1a57
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdtDxe.c
@@ -0,0 +1,229 @@ 
+/** @file
+*  Device tree enumeration DXE driver for AArch64 VMs
+*
+*  Copyright (c) 2014, 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 <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/VirtioMmioDeviceLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DxeServicesLib.h>
+#include <libfdt.h>
+
+#include <Guid/Fdt.h>
+
+#pragma pack (1)
+typedef struct {
+  VENDOR_DEVICE_PATH                  Vendor;
+  UINT32                              Instance;
+  EFI_DEVICE_PATH_PROTOCOL            End;
+} VIRTIO_BLK_DEVICE_PATH;
+#pragma pack ()
+
+static struct _Ptypes {
+  enum _Ptype {
+    UNKNOWN, GIC, RTC, VIRTIO, UART, TIMER
+  }         Ptype;
+  CHAR8     Comp[20];
+} const Ptypes[] = {
+  { GIC,     "arm,cortex-a15-gic"  },
+  { RTC,     "arm,pl031"           },
+  { VIRTIO,  "virtio,mmio"         },
+  { UART,    "arm,pl011"           },
+  { TIMER,   "arm,armv7-timer"     },
+  { TIMER,   "arm,armv8-timer"     },
+  { UNKNOWN, ""                    }
+};
+
+enum _Ptype GetTypeFromNode (CHAR8 CONST *NodeType, INT32 Size)
+{
+  CHAR8 CONST *s;
+
+  /*
+   * A 'compatible' node may contain a sequence of NULL terminated
+   * compatible strings so check each one
+   */
+  for (s = NodeType; s < NodeType + Size && *s; s += 1 + AsciiStrLen (s)) {
+    struct _Ptypes const *Type;
+
+    for (Type = Ptypes; Type->Comp[0]; Type++)
+      if (AsciiStrCmp (Type->Comp, s) == 0)
+        return Type->Ptype;
+  }
+  return UNKNOWN;
+}
+
+EFI_STATUS
+EFIAPI
+InitializeVirtFdtDxe (
+  IN EFI_HANDLE           ImageHandle,
+  IN EFI_SYSTEM_TABLE     *SystemTable
+  )
+{
+  VOID        *FdtImageData;
+  VOID        *MemoryBase;
+  INT32       Node, Prev, VirtIoInstance;
+  EFI_STATUS  Status;
+
+  MemoryBase = (VOID *)PcdGet64 (PcdSystemMemoryBase);
+
+  if (fdt_check_header (MemoryBase) != 0) {
+    DEBUG ((EFI_D_ERROR, "InitializeVirtFdtDxe: No DTB found @ 0x%08x\n",
+          MemoryBase));
+    return EFI_NOT_FOUND;
+  }
+
+  FdtImageData = AllocatePages (EFI_SIZE_TO_PAGES (fdt_totalsize (MemoryBase)));
+  if (FdtImageData == NULL) {
+    DEBUG ((EFI_D_ERROR, "InitializeVirtFdtDxe: AllocatePages() failed\n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  CopyMem (FdtImageData, MemoryBase, fdt_totalsize (MemoryBase));
+  Status = gBS->InstallConfigurationTable (&gFdtTableGuid, FdtImageData);
+  ASSERT_EFI_ERROR (Status);
+
+  DEBUG ((EFI_D_ERROR, "InitializeVirtFdtDxe: DTB @ 0x%08x\n", FdtImageData));
+
+  /*
+   * Now enumerate the nodes and install peripherals that we are interested in,
+   * i.e., GIC, RTC and virtio MMIO nodes
+   */
+  Status = EFI_SUCCESS;
+
+  for (Prev = VirtIoInstance = 0; Status == EFI_SUCCESS; Prev = Node) {
+    CONST CHAR8                 *Type;
+    INT32                       Len;
+    enum _Ptype                 Ptype;
+    VOID CONST                  *RegProp;
+
+    Node = fdt_next_node (MemoryBase, Prev, NULL);
+    if (Node < 0)
+      break;
+
+    Type = fdt_getprop (MemoryBase, Node, "compatible", &Len);
+    if (Type == NULL)
+      continue;
+
+    Ptype = GetTypeFromNode (Type, Len);
+    if (Ptype == UNKNOWN)
+      continue;
+
+    /*
+     * Get the 'reg' property of this node. For now, we will assume
+     * 8 byte quantities for base and size, respectively.
+     * TODO use #cells root properties instead
+     */
+    RegProp = fdt_getprop (MemoryBase, Node, "reg", &Len);
+    ASSERT (RegProp != NULL || Ptype == TIMER);
+
+    switch (Ptype) {
+      VIRTIO_BLK_DEVICE_PATH  *DevicePath;
+      EFI_HANDLE              Handle;
+      UINT64                  RegBase;
+      UINT32                  DistBase, CpuBase;
+      
+    case VIRTIO:
+      /* Create a unique device path for this transport on the fly */
+      DevicePath = (VIRTIO_BLK_DEVICE_PATH *)CreateDeviceNode (
+                                    HARDWARE_DEVICE_PATH,
+                                    HW_VENDOR_DP,
+                                    sizeof (VIRTIO_BLK_DEVICE_PATH));
+
+      CopyMem (&DevicePath->Vendor.Guid, &gEfiCallerIdGuid, sizeof (EFI_GUID));
+      DevicePath->Instance = VirtIoInstance++;
+      SetDevicePathNodeLength (&DevicePath->Vendor,
+                              sizeof (*DevicePath) - sizeof (DevicePath->End));
+      SetDevicePathEndNode (&DevicePath->End);
+
+      Handle = NULL;
+      Status = gBS->InstallProtocolInterface (&Handle,
+                     &gEfiDevicePathProtocolGuid, EFI_NATIVE_INTERFACE,
+                     DevicePath);
+      if (EFI_ERROR (Status)) {
+        DEBUG ((EFI_D_ERROR, "Failed to install VirtIO protocol interface\n"));
+        break;
+      }
+
+      RegBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);
+      Status = VirtioMmioInstallDevice (RegBase, Handle);
+      if (EFI_ERROR (Status))
+        DEBUG ((EFI_D_ERROR, "Failed to install VirtIO transport @ 0x%x\n",
+                RegBase));
+      break;
+
+    case GIC:
+      ASSERT (Len == 32);
+
+      DistBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);
+      CpuBase = fdt64_to_cpu (((UINT64 *)RegProp)[2]);
+      PcdSet32 (PcdGicDistributorBase, DistBase);
+      PcdSet32 (PcdGicInterruptInterfaceBase, CpuBase);
+
+      DEBUG ((EFI_D_ERROR, "Found GIC @ 0x%x/0x%x\n", DistBase, CpuBase));
+      break;
+
+    case RTC:
+      ASSERT (Len == 16);
+      
+      RegBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);
+      PcdSet32 (PcdPL031RtcBase, (UINT32)RegBase);
+
+      DEBUG ((EFI_D_ERROR, "Found PL031 RTC @ 0x%x\n", RegBase));
+      break;
+
+    case TIMER: {
+      struct {
+        UINT32  Type;
+        UINT32  Number;
+        UINT32  Flags;
+      } const *Interrupts;
+      INT32 SecIntrNum, IntrNum, VirtIntrNum, HypIntrNum;
+
+      /*
+       * - interrupts : Interrupt list for secure, non-secure, virtual and
+       *  hypervisor timers, in that order.
+       */
+      Interrupts = fdt_getprop (MemoryBase, Node, "interrupts", &Len);
+      ASSERT (Len == 48);
+
+      SecIntrNum = fdt32_to_cpu (Interrupts[0].Number)
+                   + (Interrupts[0].Type ? 16 : 0);
+      IntrNum = fdt32_to_cpu (Interrupts[1].Number)
+                + (Interrupts[1].Type ? 16 : 0);
+      VirtIntrNum = fdt32_to_cpu (Interrupts[2].Number)
+                    + (Interrupts[2].Type ? 16 : 0);
+      HypIntrNum = fdt32_to_cpu (Interrupts[3].Number)
+                   + (Interrupts[3].Type ? 16 : 0);
+      
+      DEBUG ((EFI_D_ERROR, "Found Timer interrupts %d, %d, %d, %d\n",
+        SecIntrNum, IntrNum, VirtIntrNum, HypIntrNum));
+
+      PcdSet32 (PcdArmArchTimerSecIntrNum, SecIntrNum);
+      PcdSet32 (PcdArmArchTimerIntrNum, IntrNum);
+      PcdSet32 (PcdArmArchTimerVirtIntrNum, VirtIntrNum);
+      PcdSet32 (PcdArmArchTimerHypIntrNum, HypIntrNum);
+      break;
+    }
+
+    default:
+      break;
+    }
+  }
+  return Status;
+}
diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Include/Platform/KVM/ArmPlatform.h b/ArmPlatformPkg/AArch64VirtualizationPkg/Include/Platform/KVM/ArmPlatform.h
new file mode 100644
index 000000000000..f6f694f54390
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Include/Platform/KVM/ArmPlatform.h
@@ -0,0 +1,32 @@ 
+/** @file
+*  Header defining KVM constants (Base addresses, sizes, flags)
+*
+*  Copyright (c) 2011, ARM Limited. All rights reserved.
+*  Copyright (c) 2014, Linaro Limited
+*
+*  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_KVM_H__
+#define __ARM_KVM_H__
+
+/*
+ * We don't care about this value, but the PL031 driver depends on the macro
+ * to exist: it will pass it on to our ArmPlatformSysConfigLib:ConfigGet()
+ * function, which just returns EFI_UNSUPPORTED.
+ */
+#define SYS_CFG_RTC       0x0
+
+#define PSCI_0_2_FN_BASE               0x84000000
+#define PSCI_0_2_FN(n)                 (PSCI_0_2_FN_BASE + (n))
+#define PSCI_0_2_FN_SYSTEM_OFF         PSCI_0_2_FN(8)
+#define PSCI_0_2_FN_SYSTEM_RESET       PSCI_0_2_FN(9)
+
+#endif
diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/AArch64KVMLib.inf b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/AArch64KVMLib.inf
new file mode 100644
index 000000000000..7e5d5c573ac3
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/AArch64KVMLib.inf
@@ -0,0 +1,53 @@ 
+#/* @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.
+#
+#*/
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = AArch64KVMLib
+  FILE_GUID                      = 00214cc1-06d1-45fe-9700-dca5726ad7bf
+  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
+  PrintLib
+  FdtLib
+
+[Sources.common]
+  KVM.c
+  KVMMem.c
+
+[Sources.AARCH64]
+  KVMHelper.S      | GCC
+
+[FeaturePcd]
+  gEmbeddedTokenSpaceGuid.PcdCacheEnable
+
+[Pcd]
+  gArmTokenSpaceGuid.PcdSystemMemoryBase
+  gArmTokenSpaceGuid.PcdSystemMemorySize
+
+[FixedPcd]
+  gArmTokenSpaceGuid.PcdArmPrimaryCoreMask
+  gArmTokenSpaceGuid.PcdArmPrimaryCore
+
+  gArmPlatformTokenSpaceGuid.PcdCoreCount
diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVM.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVM.c
new file mode 100644
index 000000000000..dcbe076f5d58
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVM.c
@@ -0,0 +1,127 @@ 
+/** @file
+*
+*  Copyright (c) 2011-2013, 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.
+*
+**/
+
+#include <Library/IoLib.h>
+#include <Library/ArmPlatformLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <ArmPlatform.h>
+#include <libfdt.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;
+}
+
+/**
+  Initialize controllers that must setup in the normal world
+
+  This function is called by the ArmPlatformPkg/Pei or ArmPlatformPkg/Pei/PlatformPeim
+  in the PEI phase.
+
+**/
+RETURN_STATUS
+ArmPlatformInitialize (
+  IN  UINTN                     MpId
+  )
+{
+  return RETURN_SUCCESS;
+}
+
+/**
+  Initialize the system (or sometimes called permanent) memory
+
+  This memory is generally represented by the DRAM.
+
+**/
+VOID
+ArmPlatformInitializeSystemMemory (
+  VOID
+  )
+{
+  VOID   *SystemMemoryBase;
+  INT32   Node, Prev;
+
+  SystemMemoryBase = (VOID *)PcdGet64 (PcdSystemMemoryBase);
+
+  /*
+   * Make sure we have a valid device tree blob at the base of DRAM
+   */
+  if (fdt_check_header (SystemMemoryBase) != 0)
+    return;
+
+  /*
+   * Look for a memory node
+   * TODO handle disjoint memory
+   */
+  for (Prev = 0;; Prev = Node) {
+    CONST CHAR8  *Type;
+    INT32         Len;
+
+    Node = fdt_next_node (SystemMemoryBase, Prev, NULL);
+    if (Node < 0)
+      return;
+
+    Type = fdt_getprop (SystemMemoryBase, Node, "device_type", &Len);
+    if (Type && AsciiStrnCmp (Type, "memory", Len) == 0) {
+      UINT64 CONST *RegProp;
+
+      /*
+       * Get the 'reg' property of this node. For now, we will assume
+       * two 8 byte quantities for base and size, respectively.
+       * TODO use #cells root properties instead
+       */
+      RegProp = fdt_getprop (SystemMemoryBase, Node, "reg", &Len);
+      if (RegProp != 0 && Len == (2 * sizeof (UINT64))) {
+        UINT64 NewBase, NewSize;
+
+        NewBase = fdt64_to_cpu (RegProp[0]);
+        NewSize = fdt64_to_cpu (RegProp[1]);
+
+        PcdSet64 (PcdSystemMemoryBase, NewBase);
+        PcdSet64 (PcdSystemMemorySize, NewSize);
+
+        DEBUG ((EFI_D_ERROR, "KVM: System RAM @ 0x%lx - 0x%lx\n",
+           NewBase, NewBase + NewSize - 1));
+      }
+      continue;
+    }
+  }
+}
+
+EFI_PEI_PPI_DESCRIPTOR      gPlatformPpiTable[] = {
+};
+
+VOID
+ArmPlatformGetPlatformPpiList (
+  OUT UINTN                   *PpiListSize,
+  OUT EFI_PEI_PPI_DESCRIPTOR  **PpiList
+  )
+{
+  *PpiListSize = sizeof (gPlatformPpiTable);
+  *PpiList = gPlatformPpiTable;
+}
diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMHelper.S b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMHelper.S
new file mode 100644
index 000000000000..f5afb4146313
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMHelper.S
@@ -0,0 +1,70 @@ 
+#
+#  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(ArmGetCpuCountPerCluster)
+
+GCC_ASM_IMPORT(_gPcd_FixedAtBuild_PcdArmPrimaryCore)
+GCC_ASM_IMPORT(_gPcd_FixedAtBuild_PcdArmPrimaryCoreMask)
+GCC_ASM_IMPORT(_gPcd_FixedAtBuild_PcdCoreCount)
+
+ASM_PFX(ArmPlatformPeiBootAction):
+  ret
+
+//UINTN
+//ArmPlatformGetPrimaryCoreMpId (
+//  VOID
+//  );
+ASM_PFX(ArmPlatformGetPrimaryCoreMpId):
+  LoadConstantToReg (_gPcd_FixedAtBuild_PcdArmPrimaryCore, x0)
+  ldrh   w0, [x0]
+  ret
+
+# IN None
+# OUT x0 = number of cores present in the system
+ASM_PFX(ArmGetCpuCountPerCluster):
+  mov	x0, #1
+  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
+
+ASM_FUNCTION_REMOVE_IF_UNREFERENCED
diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMMem.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMMem.c
new file mode 100644
index 000000000000..55dcf31a5666
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMMem.c
@@ -0,0 +1,106 @@ 
+/** @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/ArmPlatformLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/ArmPlatformGlobalVariableLib.h>
+#include <ArmPlatform.h>
+
+// Number of Virtual Memory Map Descriptors without a Logic Tile
+#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS          4
+
+// 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;
+  ARM_MEMORY_REGION_DESCRIPTOR  *VirtualMemoryTable;
+  EFI_PHYSICAL_ADDRESS          PhysAddrTop;
+
+  static INT16 const PARange[] = { 32, 36, 40, 42, 44, 48, -1, -1 };
+
+  ASSERT (VirtualMemoryMap != NULL);
+
+  /*
+   * Get the max phys address from the CPU config registers
+   */
+  asm ("mrs  %0, id_aa64mmfr0_el1" : "=r" (PhysAddrTop));
+  PhysAddrTop = 1ULL << PARange[PhysAddrTop & 7];
+  ASSERT (PhysAddrTop != 0);
+
+  VirtualMemoryTable = AllocatePages (EFI_SIZE_TO_PAGES (
+                                     sizeof (ARM_MEMORY_REGION_DESCRIPTOR)
+                                     * MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS));
+  if (VirtualMemoryTable == NULL) {
+	  DEBUG ((EFI_D_ERROR, "ArmPlatformGetVirtualMemoryMap: Error: Failed AllocatePages()\n"));
+      return;
+  }
+
+  if (FeaturePcdGet (PcdCacheEnable) == TRUE) {
+      CacheAttributes = DDR_ATTRIBUTES_CACHED;
+  } else {
+      CacheAttributes = DDR_ATTRIBUTES_UNCACHED;
+  }
+
+  // System DRAM
+  VirtualMemoryTable[0].PhysicalBase = PcdGet64 (PcdSystemMemoryBase);
+  VirtualMemoryTable[0].VirtualBase  = VirtualMemoryTable[0].PhysicalBase;
+  VirtualMemoryTable[0].Length       = PcdGet64 (PcdSystemMemorySize);
+  VirtualMemoryTable[0].Attributes   = CacheAttributes;
+
+  DEBUG ((EFI_D_ERROR, "ArmPlatformGetVirtualMemoryMap: Dumping DDR Memory Map:\n \
+		  DDR PhysicalBase: 0x%lX\n \
+		  VirtualBase: 0x%lX\n \
+		  Length: 0x%lX\n",
+		  VirtualMemoryTable[0].PhysicalBase,
+		  VirtualMemoryTable[0].VirtualBase,
+		  VirtualMemoryTable[0].Length));
+
+  // Peripheral space before DRAM
+  VirtualMemoryTable[1].PhysicalBase = 0x0;
+  VirtualMemoryTable[1].VirtualBase  = 0x0;
+  VirtualMemoryTable[1].Length       = VirtualMemoryTable[0].PhysicalBase;
+  VirtualMemoryTable[1].Attributes   = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+
+  // Peripheral space after DRAM
+  VirtualMemoryTable[2].PhysicalBase = VirtualMemoryTable[0].Length + VirtualMemoryTable[1].Length;
+  VirtualMemoryTable[2].VirtualBase  = VirtualMemoryTable[2].PhysicalBase;
+  VirtualMemoryTable[2].Length       = PhysAddrTop - VirtualMemoryTable[2].PhysicalBase;
+  VirtualMemoryTable[2].Attributes   = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+
+  // End of Table
+  VirtualMemoryTable[3] = (ARM_MEMORY_REGION_DESCRIPTOR){};
+
+  *VirtualMemoryMap = VirtualMemoryTable;
+}
diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationSysConfigLibKVM/AArch64VirtualizationSysConfigLibKVM.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationSysConfigLibKVM/AArch64VirtualizationSysConfigLibKVM.c
new file mode 100644
index 000000000000..514d9358964c
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationSysConfigLibKVM/AArch64VirtualizationSysConfigLibKVM.c
@@ -0,0 +1,95 @@ 
+/** @file  AArch64VirtualizationSysConfigLibKVM.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>
+
+
+/****************************************************************************
+ *
+ * Stub for KVM at the moment
+ *
+ ****************************************************************************/
+
+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
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
+
+RETURN_STATUS
+ArmPlatformSysConfigGet (
+  IN  SYS_CONFIG_FUNCTION   Function,
+  OUT UINT32*               Value
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
+
+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
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
+
+RETURN_STATUS
+ArmPlatformSysConfigSetDevice (
+  IN  SYS_CONFIG_FUNCTION   Function,
+  IN  UINT32                Device,
+  IN  UINT32                Value
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationSysConfigLibKVM/AArch64VirtualizationSysConfigLibKVM.inf b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationSysConfigLibKVM/AArch64VirtualizationSysConfigLibKVM.inf
new file mode 100644
index 000000000000..d4a495147de5
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationSysConfigLibKVM/AArch64VirtualizationSysConfigLibKVM.inf
@@ -0,0 +1,35 @@ 
+#/** @file
+#  
+#  Component description file for AArch64VirtualizationSysConfigLib module
+#  
+#  Copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR>
+#  Copyright (c) 2014, 
+#
+#  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                      = AArch64VirtualizationSysConfigLibKVM
+  FILE_GUID                      = b5988e68-a2cc-49ac-9ca8-8cc78420ae45
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = ArmPlatformSysConfigLib
+  
+[Sources.common]
+  AArch64VirtualizationSysConfigLibKVM.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  IoLib
diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.c
new file mode 100644
index 000000000000..e5edbc407b56
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.c
@@ -0,0 +1,96 @@ 
+/** @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>
+
+  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/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/EfiResetSystemLib.h>
+
+#include <ArmPlatform.h>
+
+/**
+  Resets the entire platform.
+
+  @param  ResetType             The type of reset to perform.
+  @param  ResetStatus           The status code for the reset.
+  @param  DataSize              The size, in bytes, of WatchdogData.
+  @param  ResetData             For a ResetType of EfiResetCold, EfiResetWarm, or
+                                EfiResetShutdown the data buffer starts with a Null-terminated
+                                Unicode string, optionally followed by additional binary data.
+
+**/
+EFI_STATUS
+EFIAPI
+LibResetSystem (
+  IN EFI_RESET_TYPE   ResetType,
+  IN EFI_STATUS       ResetStatus,
+  IN UINTN            DataSize,
+  IN CHAR16           *ResetData OPTIONAL
+  )
+{
+  register UINTN Rx asm ("x0");
+
+  switch (ResetType) {
+
+  case EfiResetPlatformSpecific:
+    // Map the platform specific reset as reboot
+  case EfiResetWarm:
+    // Map a warm reset into a cold reset
+  case EfiResetCold:
+    // Send a PSCI 0.2 SYSTEM_RESET command
+    Rx = PSCI_0_2_FN_SYSTEM_RESET;
+    break;
+  case EfiResetShutdown:
+    // Send a PSCI 0.2 SYSTEM_OFF command
+    Rx = PSCI_0_2_FN_SYSTEM_OFF;
+    break;
+
+  default:
+    ASSERT (FALSE);
+    return EFI_UNSUPPORTED;
+  }
+
+  /*
+   * Being a virtualized platform, we are allowed to assume that we
+   * are running at EL1, so HVC is appropriate for making PSCI calls.
+   */
+  asm ("hvc #0" :: "r" (Rx));
+
+  // We should never be here
+  while (1);
+}
+
+/**
+  Initialize any infrastructure required for LibResetSystem () to function.
+
+  @param  ImageHandle   The firmware allocated handle for the EFI image.
+  @param  SystemTable   A pointer to the EFI System Table.
+  
+  @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+LibInitializeResetSystem (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  return EFI_SUCCESS;
+}
diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.inf b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.inf
new file mode 100644
index 000000000000..2321c2115bb1
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.inf
@@ -0,0 +1,33 @@ 
+#/** @file
+# Reset System lib to make it easy to port new platforms
+#
+# Copyright (c) 2008, Apple Inc. 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                      = ResetSystemLib
+  FILE_GUID                      = DC9CCFDD-2638-474B-8F5D-031B758C12FC
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = EfiResetSystemLib
+
+[Sources.common]
+  ResetSystemLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+  DebugLib
+  BaseLib