diff mbox

[edk2,v3,09/10] ArmPlatformPkg: add support for a QEMU/mach-virt target

Message ID 1409152378-19706-10-git-send-email-ard.biesheuvel@linaro.org
State New
Headers show

Commit Message

Ard Biesheuvel Aug. 27, 2014, 3:12 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                  | 222 ++++++++++++++
 .../AArch64Virtualization-KVM.fdf                  | 307 +++++++++++++++++++
 .../AArch64Virtualization.dsc.inc                  | 336 +++++++++++++++++++++
 .../AArch64VirtualizationPkg/Driver/VirtFdt.inf    |  61 ++++
 .../AArch64VirtualizationPkg/Driver/VirtFdtDxe.c   | 249 +++++++++++++++
 .../Include/Platform/KVM/ArmPlatform.h             |  27 ++
 .../AArch64VirtualizationLibKVM/AArch64KVMLib.inf  |  57 ++++
 .../Library/AArch64VirtualizationLibKVM/KVM.c      | 143 +++++++++
 .../AArch64VirtualizationLibKVM/KVMHelper.S        |  86 ++++++
 .../Library/AArch64VirtualizationLibKVM/KVMMem.c   | 102 +++++++
 .../AArch64VirtualizationSysConfigLibKVM.c         |  95 ++++++
 .../AArch64VirtualizationSysConfigLibKVM.inf       |  35 +++
 .../Library/PlatformPei/PlatformPeiLib.c           |  47 +++
 .../Library/PlatformPei/PlatformPeiLib.inf         |  58 ++++
 .../Library/ResetSystemLib/ResetSystemLib.c        |  97 ++++++
 .../Library/ResetSystemLib/ResetSystemLib.inf      |  36 +++
 .../Library/ResetSystemLib/ResetSystemPsci.S       |  40 +++
 17 files changed, 1998 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 100755 ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformPeiLib.c
 create mode 100755 ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformPeiLib.inf
 create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.c
 create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.inf
 create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemPsci.S

Comments

Olivier Martin Aug. 27, 2014, 6:15 p.m. UTC | #1
I have been through the patchset yet. But I noticed the name of the platform
in another email.
Is this new platform AArch64 specific? Could we imagine this platform being
easily ported to ARMv7 (with Virtualization extension)?
If yes, we should maybe rename it 'ArmVirtualizationPkg' to avoid to
duplicate the code if someone does the port at some point.

> -----Original Message-----
> From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org]
> Sent: 27 August 2014 16:13
> To: lersek@redhat.com; Olivier Martin; edk2-
> devel@lists.sourceforge.net; peter.maydell@linaro.org;
> christoffer.dall@linaro.org; drjones@redhat.com;
> ilias.biris@linaro.org; leif.lindholm@linaro.org
> Cc: Ard Biesheuvel; Michael Casadevall
> Subject: [PATCH v3 09/10] ArmPlatformPkg: add support for a QEMU/mach-
> virt target
> 
> 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                  | 222
> ++++++++++++++
>  .../AArch64Virtualization-KVM.fdf                  | 307
> +++++++++++++++++++
>  .../AArch64Virtualization.dsc.inc                  | 336
> +++++++++++++++++++++
>  .../AArch64VirtualizationPkg/Driver/VirtFdt.inf    |  61 ++++
>  .../AArch64VirtualizationPkg/Driver/VirtFdtDxe.c   | 249
> +++++++++++++++
>  .../Include/Platform/KVM/ArmPlatform.h             |  27 ++
>  .../AArch64VirtualizationLibKVM/AArch64KVMLib.inf  |  57 ++++
>  .../Library/AArch64VirtualizationLibKVM/KVM.c      | 143 +++++++++
>  .../AArch64VirtualizationLibKVM/KVMHelper.S        |  86 ++++++
>  .../Library/AArch64VirtualizationLibKVM/KVMMem.c   | 102 +++++++
>  .../AArch64VirtualizationSysConfigLibKVM.c         |  95 ++++++
>  .../AArch64VirtualizationSysConfigLibKVM.inf       |  35 +++
>  .../Library/PlatformPei/PlatformPeiLib.c           |  47 +++
>  .../Library/PlatformPei/PlatformPeiLib.inf         |  58 ++++
>  .../Library/ResetSystemLib/ResetSystemLib.c        |  97 ++++++
>  .../Library/ResetSystemLib/ResetSystemLib.inf      |  36 +++
>  .../Library/ResetSystemLib/ResetSystemPsci.S       |  40 +++
>  17 files changed, 1998 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/ArmPlatfor
> m.h
>  create mode 100644
> ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLi
> bKVM/AArch64KVMLib.inf
>  create mode 100644
> ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLi
> bKVM/KVM.c
>  create mode 100644
> ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLi
> bKVM/KVMHelper.S
>  create mode 100644
> ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLi
> bKVM/KVMMem.c
>  create mode 100644
> ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationSy
> sConfigLibKVM/AArch64VirtualizationSysConfigLibKVM.c
>  create mode 100644
> ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationSy
> sConfigLibKVM/AArch64VirtualizationSysConfigLibKVM.inf
>  create mode 100755
> ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformPei
> Lib.c
>  create mode 100755
> ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformPei
> Lib.inf
>  create mode 100644
> ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSys
> temLib.c
>  create mode 100644
> ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSys
> temLib.inf
>  create mode 100644
> ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSys
> temPsci.S
> 
> diff --git
> a/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization-KVM.dsc
> b/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization-KVM.dsc
> new file mode 100644
> index 000000000000..89c5ff134b41
> --- /dev/null
> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization-
> KVM.dsc
> @@ -0,0 +1,222 @@
> +#
> +#  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/AArch64V
> irtualizationLibKVM/AArch64KVMLib.inf
> +
> +  # Virtio Support
> +  VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
> +
> VirtioMmioDeviceLib|OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevic
> eLib.inf
> +
> +
> ArmPlatformSysConfigLib|ArmPlatformPkg/AArch64VirtualizationPkg/Library
> /AArch64VirtualizationSysConfigLibKVM/AArch64VirtualizationSysConfigLib
> KVM.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|0x80000040
> +
> +  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
> +
> +  #
> +  # 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
> +  #
> +  gArmPlatformTokenSpaceGuid.PcdDefaultBootDescription|L"Linux (EFI
> stub) on virtio31:hd0:part0"
> +
> gArmPlatformTokenSpaceGuid.PcdDefaultBootDevicePath|L"VenHw(837DCA9E-
> E874-4D82-B29A-
> 23FE0E23D1E2,003E000A00000000)/HD(1,MBR,0x00000000,0x3F,0x19FC0)/Image"
> +  gArmPlatformTokenSpaceGuid.PcdDefaultBootArgument|"root=/dev/vda2
> console=ttyAMA0,38400n8 earlycon=pl011,0x9000000 uefi_debug"
> +  gArmPlatformTokenSpaceGuid.PcdDefaultBootType|0
> +
> +   # 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)/VenVt100()"
> +  gArmPlatformTokenSpaceGuid.PcdDefaultConInPaths|L"VenHw(D3987D4B-
> 971A-435F-8CAF-4967EB627241)/Uart(38400,8,N,1)/VenVt100()"
> +  gArmPlatformTokenSpaceGuid.PcdPlatformBootTimeOut|3
> +
> +  #
> +  # 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
> +
> +  # location of the device tree blob passed by QEMU
> +  gArmTokenSpaceGuid.PcdDeviceTreeBaseAddress|0x40000000
> +
> +  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/ArmPlatformGlobalVa
> riableLib/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/LzmaCustom
> DecompressLib.inf
> +  }
> +
> +  #
> +  # DXE
> +  #
> +  MdeModulePkg/Core/Dxe/DxeMain.inf {
> +    <LibraryClasses>
> +
> NULL|MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32Guide
> dSectionExtractLib.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/MonotonicCounterRunti
> meDxe.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.in
> f
> +  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..78efb8dbb100
> --- /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, put 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/MonotonicCounterRunti
> meDxe.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.in
> f
> +  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..67c024feb086
> --- /dev/null
> +++
> b/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization.dsc.inc
> @@ -0,0 +1,336 @@
> +#
> +#  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.i
> nf
> +
> UncachedMemoryAllocationLib|ArmPkg/Library/UncachedMemoryAllocationLib/
> UncachedMemoryAllocationLib.inf
> +#
> UncachedMemoryAllocationLib|ArmPkg/Library/DebugUncachedMemoryAllocatio
> nLib/DebugUncachedMemoryAllocationLib.inf
> +!endif
> +
> DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/Base
> DebugPrintErrorLevelLib.inf
> +
> +  BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
> +
> SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchroniz
> ationLib.inf
> +
> PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLib
> Null.inf
> +  PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
> +
> PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePe
> CoffGetEntryPointLib.inf
> +  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
> +  IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
> +
> UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompre
> ssLib.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/UefiBo
> otServicesTableLib.inf
> +
> DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTable
> Lib.inf
> +
> UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntr
> yPoint.inf
> +
> UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/Uefi
> ApplicationEntryPoint.inf
> +  HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
> +
> UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServi
> cesLib.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/ArmCacheMaint
> enanceLib.inf
> +
> DefaultExceptionHandlerLib|ArmPkg/Library/DefaultExceptionHandlerLib/De
> faultExceptionHandlerLib.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/ArmPlatf
> ormStackLib.inf
> +  ArmSmcLib|ArmPkg/Library/ArmSmcLib/ArmSmcLib.inf
> +
> +
> PlatformPeiLib|ArmPlatformPkg/AArch64VirtualizationPkg/Library/Platform
> Pei/PlatformPeiLib.inf
> +
> EfiResetSystemLib|ArmPlatformPkg/AArch64VirtualizationPkg/Library/Reset
> SystemLib/ResetSystemLib.inf
> +
> +  # ARM PL111 Lcd Driver
> +
> LcdPlatformLib|ArmPlatformPkg/ArmVExpressPkg/Library/PL111LcdArmVExpres
> sLib/PL111LcdArmVExpressLib.inf
> +  # ARM PL031 RTC Driver
> +
> RealTimeClockLib|ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031Real
> TimeClockLib.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/PL011SerialPort
> Lib.inf
> +
> SerialPortExtLib|ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialP
> ortExtLib.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/E
> blAddExternalCommandLib.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/RvdPeCoffE
> xtraActionLib.inf
> +
> PeCoffExtraActionLib|ArmPkg/Library/DebugPeCoffExtraActionLib/DebugPeCo
> ffExtraActionLib.inf
> +
> #PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BaseP
> eCoffExtraActionLibNull.inf
> +
> +
> DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.
> inf
> +
> DebugAgentTimerLib|EmbeddedPkg/Library/DebugAgentTimerLibNull/DebugAgen
> tTimerLibNull.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/DebugSecExtraAction
> Lib/DebugSecExtraActionLib.inf
> +
> ArmPlatformGlobalVariableLib|ArmPlatformPkg/Library/ArmPlatformGlobalVa
> riableLib/Sec/SecArmPlatformGlobalVariableLib.inf
> +
> +
> DebugAgentLib|ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentSymbols
> BaseLib.inf
> +
> DefaultExceptionHandlerLib|ArmPkg/Library/DefaultExceptionHandlerLib/De
> faultExceptionHandlerLibBase.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/PeiMemoryAllo
> cationLib.inf
> +
> PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.in
> f
> +
> PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib
> .inf
> +
> ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiRepo
> rtStatusCodeLib.inf
> +
> OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemH
> ookStatusCodeLibNull.inf
> +
> PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePe
> CoffGetEntryPointLib.inf
> +
> UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompre
> ssLib.inf
> +
> ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiEx
> tractGuidedSectionLib.inf
> +
> +
> ArmPlatformGlobalVariableLib|ArmPlatformPkg/Library/ArmPlatformGlobalVa
> riableLib/Pei/PeiArmPlatformGlobalVariableLib.inf
> +
> PeiServicesTablePointerLib|ArmPlatformPkg/Library/PeiServicesTablePoint
> erLib/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/PeiMemoryAllo
> cationLib.inf
> +  PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
> +
> PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib
> .inf
> +
> ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiRepo
> rtStatusCodeLib.inf
> +
> OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemH
> ookStatusCodeLibNull.inf
> +
> PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePe
> CoffGetEntryPointLib.inf
> +
> PeiResourcePublicationLib|MdePkg/Library/PeiResourcePublicationLib/PeiR
> esourcePublicationLib.inf
> +
> UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompre
> ssLib.inf
> +
> ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiEx
> tractGuidedSectionLib.inf
> +
> +
> ArmPlatformGlobalVariableLib|ArmPlatformPkg/Library/ArmPlatformGlobalVa
> riableLib/Pei/PeiArmPlatformGlobalVariableLib.inf
> +
> PeiServicesTablePointerLib|ArmPlatformPkg/Library/PeiServicesTablePoint
> erLib/PeiServicesTablePointerLib.inf
> +
> +[LibraryClasses.common.DXE_CORE]
> +  HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
> +
> MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/Dxe
> CoreMemoryAllocationLib.inf
> +
> DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.in
> f
> +
> ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCode
> LibFramework/DxeReportStatusCodeLib.inf
> +
> ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeEx
> tractGuidedSectionLib.inf
> +
> UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompre
> ssLib.inf
> +  DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
> +
> PerformanceLib|MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerfor
> manceLib.inf
> +
> +[LibraryClasses.common.DXE_DRIVER]
> +
> ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCode
> LibFramework/DxeReportStatusCodeLib.inf
> +  DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
> +
> SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/Dxe
> SecurityManagementLib.inf
> +
> PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib
> .inf
> +
> MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAl
> locationLib.inf
> +
> ArmPlatformGlobalVariableLib|ArmPlatformPkg/Library/ArmPlatformGlobalVa
> riableLib/Dxe/DxeArmPlatformGlobalVariableLib.inf
> +
> +[LibraryClasses.common.UEFI_APPLICATION]
> +
> UefiDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDe
> compressLib/BaseUefiTianoCustomDecompressLib.inf
> +
> PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib
> .inf
> +
> MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAl
> locationLib.inf
> +  HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
> +
> +[LibraryClasses.common.UEFI_DRIVER]
> +
> ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCode
> LibFramework/DxeReportStatusCodeLib.inf
> +
> UefiDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDe
> compressLib/BaseUefiTianoCustomDecompressLib.inf
> +
> ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeEx
> tractGuidedSectionLib.inf
> +
> PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib
> .inf
> +  DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
> +
> MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAl
> locationLib.inf
> +
> +[LibraryClasses.common.DXE_RUNTIME_DRIVER]
> +  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
> +
> MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAl
> locationLib.inf
> +
> ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCode
> LibFramework/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
> +
> +[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..464829607871
> --- /dev/null
> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdt.inf
> @@ -0,0 +1,61 @@
> +## @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
> +  gArmTokenSpaceGuid.PcdDeviceTreeBaseAddress
> +
> +[Protocols]
> +
> +[Depex]
> +  TRUE
> diff --git
> a/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdtDxe.c
> b/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdtDxe.c
> new file mode 100644
> index 000000000000..1ad9e929ae62
> --- /dev/null
> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdtDxe.c
> @@ -0,0 +1,249 @@
> +/** @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>
> +
> +CONST UINT32 mUint32Max = 0xFFFFFFFFU;
> +
> +#pragma pack (1)
> +typedef struct {
> +  VENDOR_DEVICE_PATH                  Vendor;
> +  UINT64                              PhysBase;
> +  EFI_DEVICE_PATH_PROTOCOL            End;
> +} VIRTIO_TRANSPORT_DEVICE_PATH;
> +#pragma pack ()
> +
> +typedef enum {
> +  PropertyTypeUnknown,
> +  PropertyTypeGic,
> +  PropertyTypeRtc,
> +  PropertyTypeVirtio,
> +  PropertyTypeUart,
> +  PropertyTypeTimer,
> +} PROPERTY_TYPE;
> +
> +typedef struct {
> +  PROPERTY_TYPE Type;
> +  CHAR8         Compatible[20];
> +} PROPERTY;
> +
> +STATIC CONST PROPERTY CompatibleProperties[] = {
> +  { PropertyTypeGic,     "arm,cortex-a15-gic"  },
> +  { PropertyTypeRtc,     "arm,pl031"           },
> +  { PropertyTypeVirtio,  "virtio,mmio"         },
> +  { PropertyTypeUart,    "arm,pl011"           },
> +  { PropertyTypeTimer,   "arm,armv7-timer"     },
> +  { PropertyTypeTimer,   "arm,armv8-timer"     },
> +  { PropertyTypeUnknown, ""                    }
> +};
> +
> +typedef struct {
> +  UINT32  Type;
> +  UINT32  Number;
> +  UINT32  Flags;
> +} INTERRUPT_PROP;
> +
> +STATIC
> +PROPERTY_TYPE
> +GetTypeFromNode (
> +  IN CONST CHAR8 *NodeType,
> +  IN UINTN       Size
> +  )
> +{
> +  CONST CHAR8 *Compatible;
> +
> +  //
> +  // A 'compatible' node may contain a sequence of NULL terminated
> +  // compatible strings so check each one
> +  //
> +  for (Compatible = NodeType; Compatible < NodeType + Size &&
> *Compatible;
> +       Compatible += 1 + AsciiStrLen (Compatible)) {
> +
> +    CONST PROPERTY *CompProp;
> +
> +    for (CompProp = CompatibleProperties; CompProp->Compatible[0];
> CompProp++) {
> +      if (AsciiStrCmp (CompProp->Compatible, Compatible) == 0) {
> +        return CompProp->Type;
> +      }
> +    }
> +  }
> +  return PropertyTypeUnknown;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +InitializeVirtFdtDxe (
> +  IN EFI_HANDLE           ImageHandle,
> +  IN EFI_SYSTEM_TABLE     *SystemTable
> +  )
> +{
> +  VOID        *DeviceTreeBase;
> +  INT32        Node, Prev;
> +  EFI_STATUS   Status;
> +
> +  DeviceTreeBase = (VOID *)PcdGet64 (PcdDeviceTreeBaseAddress);
> +  ASSERT (DeviceTreeBase != NULL);
> +
> +  if (fdt_check_header (DeviceTreeBase) != 0) {
> +    DEBUG ((EFI_D_ERROR, "%a: No DTB found @ 0x%Lx\n", __FUNCTION__,
> DeviceTreeBase));
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  Status = gBS->InstallConfigurationTable (&gFdtTableGuid,
> DeviceTreeBase);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  DEBUG ((EFI_D_INFO, "%a: DTB @ 0x%p\n", __FUNCTION__,
> DeviceTreeBase));
> +
> +  //
> +  // Now enumerate the nodes and install peripherals that we are
> interested in,
> +  // i.e., GIC, RTC and virtio MMIO nodes
> +  //
> +  for (Prev = 0;; Prev = Node) {
> +    CONST CHAR8                   *Type;
> +    INT32                          Len;
> +    PROPERTY_TYPE                  PropType;
> +    CONST VOID                    *RegProp;
> +    VIRTIO_TRANSPORT_DEVICE_PATH  *DevicePath;
> +    EFI_HANDLE                     Handle;
> +    UINT64                         RegBase;
> +    UINT64                         DistBase, CpuBase;
> +    CONST INTERRUPT_PROP          *InterruptProp;
> +    INT32                          SecIntrNum, IntrNum, VirtIntrNum,
> HypIntrNum;
> +
> +    Node = fdt_next_node (DeviceTreeBase, Prev, NULL);
> +    if (Node < 0)
> +      break;
> +
> +    Type = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len);
> +    if (Type == NULL)
> +      continue;
> +
> +    PropType = GetTypeFromNode (Type, Len);
> +    if (PropType == PropertyTypeUnknown)
> +      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 (DeviceTreeBase, Node, "reg", &Len);
> +    ASSERT (RegProp != NULL || PropType == PropertyTypeTimer);
> +
> +    switch (PropType) {
> +
> +    case PropertyTypeVirtio:
> +      ASSERT (Len == 16);
> +      //
> +      // Create a unique device path for this transport on the fly
> +      //
> +      RegBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);
> +      DevicePath = (VIRTIO_TRANSPORT_DEVICE_PATH *)CreateDeviceNode (
> +                                    HARDWARE_DEVICE_PATH,
> +                                    HW_VENDOR_DP,
> +                                    sizeof
> (VIRTIO_TRANSPORT_DEVICE_PATH));
> +
> +      CopyMem (&DevicePath->Vendor.Guid, &gEfiCallerIdGuid, sizeof
> (EFI_GUID));
> +      DevicePath->PhysBase = RegBase;
> +      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, "%a: Failed to install the
> EFI_DEVICE_PATH protocol on a new handle\n",
> +               __FUNCTION__));
> +        break;
> +      }
> +
> +      Status = VirtioMmioInstallDevice (RegBase, Handle);
> +      if (EFI_ERROR (Status))
> +        DEBUG ((EFI_D_ERROR, "%a: Failed to install VirtIO transport @
> 0x%Lx on handle %p\n",
> +                __FUNCTION__, RegBase, Handle));
> +      break;
> +
> +    case PropertyTypeGic:
> +      ASSERT (Len == 32);
> +
> +      DistBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);
> +      CpuBase = fdt64_to_cpu (((UINT64 *)RegProp)[2]);
> +      ASSERT (DistBase < mUint32Max);
> +      ASSERT (CpuBase < mUint32Max);
> +
> +      PcdSet32 (PcdGicDistributorBase, (UINT32)DistBase);
> +      PcdSet32 (PcdGicInterruptInterfaceBase, (UINT32)CpuBase);
> +
> +      DEBUG ((EFI_D_INFO, "Found GIC @ 0x%x/0x%x\n", DistBase,
> CpuBase));
> +      break;
> +
> +    case PropertyTypeRtc:
> +      ASSERT (Len == 16);
> +
> +      RegBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);
> +      ASSERT (RegBase < mUint32Max);
> +
> +      PcdSet32 (PcdPL031RtcBase, (UINT32)RegBase);
> +
> +      DEBUG ((EFI_D_INFO, "Found PL031 RTC @ 0x%x\n", RegBase));
> +      break;
> +
> +    case PropertyTypeTimer:
> +
> +      //
> +      // - interrupts : Interrupt list for secure, non-secure, virtual
> and
> +      //  hypervisor timers, in that order.
> +      //
> +      InterruptProp = fdt_getprop (DeviceTreeBase, Node, "interrupts",
> &Len);
> +      ASSERT (Len == 48);
> +
> +      SecIntrNum = fdt32_to_cpu (InterruptProp[0].Number)
> +                   + (InterruptProp[0].Type ? 16 : 0);
> +      IntrNum = fdt32_to_cpu (InterruptProp[1].Number)
> +                + (InterruptProp[1].Type ? 16 : 0);
> +      VirtIntrNum = fdt32_to_cpu (InterruptProp[2].Number)
> +                    + (InterruptProp[2].Type ? 16 : 0);
> +      HypIntrNum = fdt32_to_cpu (InterruptProp[3].Number)
> +                   + (InterruptProp[3].Type ? 16 : 0);
> +
> +      DEBUG ((EFI_D_INFO, "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/ArmPlatf
> orm.h
> b/ArmPlatformPkg/AArch64VirtualizationPkg/Include/Platform/KVM/ArmPlatf
> orm.h
> new file mode 100644
> index 000000000000..5a74456d123e
> --- /dev/null
> +++
> b/ArmPlatformPkg/AArch64VirtualizationPkg/Include/Platform/KVM/ArmPlatf
> orm.h
> @@ -0,0 +1,27 @@
> +/** @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
> +
> +#endif
> diff --git
> a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64Virtualization
> LibKVM/AArch64KVMLib.inf
> b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64Virtualization
> LibKVM/AArch64KVMLib.inf
> new file mode 100644
> index 000000000000..b30d70f3a1ed
> --- /dev/null
> +++
> b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64Virtualization
> LibKVM/AArch64KVMLib.inf
> @@ -0,0 +1,57 @@
> +#/* @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
> +  gArmPlatformTokenSpaceGuid.PcdSystemMemoryInitializeInSec
> +
> +[Pcd]
> +  gArmTokenSpaceGuid.PcdSystemMemoryBase
> +  gArmTokenSpaceGuid.PcdSystemMemorySize
> +  gArmTokenSpaceGuid.PcdDeviceTreeBaseAddress
> +
> +[FixedPcd]
> +  gArmTokenSpaceGuid.PcdArmPrimaryCoreMask
> +  gArmTokenSpaceGuid.PcdArmPrimaryCore
> +
> +  gArmPlatformTokenSpaceGuid.PcdCoreCount
> +  gArmTokenSpaceGuid.PcdFdBaseAddress
> +  gArmTokenSpaceGuid.PcdFdSize
> diff --git
> a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64Virtualization
> LibKVM/KVM.c
> b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64Virtualization
> LibKVM/KVM.c
> new file mode 100644
> index 000000000000..cd9edfe5138b
> --- /dev/null
> +++
> b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64Virtualization
> LibKVM/KVM.c
> @@ -0,0 +1,143 @@
> +/** @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
> +  )
> +{
> +  //
> +  // We are relying on ArmPlatformInitializeSystemMemory () being
> called from
> +  // InitializeMemory (), which only occurs if the following feature
> is disabled
> +  //
> +  ASSERT (!FeaturePcdGet (PcdSystemMemoryInitializeInSec));
> +  return RETURN_SUCCESS;
> +}
> +
> +/**
> +  Initialize the system (or sometimes called permanent) memory
> +
> +  This memory is generally represented by the DRAM.
> +
> +**/
> +VOID
> +ArmPlatformInitializeSystemMemory (
> +  VOID
> +  )
> +{
> +  VOID   *DeviceTreeBase;
> +  INT32   Node, Prev;
> +  UINT64  NewBase = 0;
> +  UINT64  NewSize = 0;
> +
> +  DeviceTreeBase = (VOID *)PcdGet64 (PcdDeviceTreeBaseAddress);
> +  ASSERT (DeviceTreeBase != NULL);
> +
> +  //
> +  // Make sure we have a valid device tree blob at the base of DRAM
> +  //
> +  if (fdt_check_header (DeviceTreeBase) != 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 (DeviceTreeBase, Prev, NULL);
> +    if (Node < 0)
> +      return;
> +
> +    Type = fdt_getprop (DeviceTreeBase, Node, "device_type", &Len);
> +    if (Type && AsciiStrnCmp (Type, "memory", Len) == 0) {
> +      CONST UINT64 *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 (DeviceTreeBase, Node, "reg", &Len);
> +      if (RegProp != 0 && Len == (2 * sizeof (UINT64))) {
> +
> +        NewBase = fdt64_to_cpu (RegProp[0]);
> +        NewSize = fdt64_to_cpu (RegProp[1]);
> +
> +        PcdSet64 (PcdSystemMemoryBase, NewBase);
> +        PcdSet64 (PcdSystemMemorySize, NewSize);
> +
> +        DEBUG ((EFI_D_INFO, "KVM: System RAM @ 0x%lx - 0x%lx\n",
> +           NewBase, NewBase + NewSize - 1));
> +      } else {
> +        DEBUG ((EFI_D_ERROR, "KVM: Failed to parse FDT memory
> node\n"));
> +      }
> +      break;
> +    }
> +  }
> +  //
> +  // We need to make sure that the machine we are running on has at
> least
> +  // 128 MB of memory configured, and does not run from shadowed NOR.
> This
> +  // prevents the device tree at base of DRAM from getting clobbered
> before we
> +  // have a chance of marking its location as reserved or moving it
> out of the
> +  // way.
> +  //
> +  ASSERT (NewSize >= SIZE_128MB);
> +  ASSERT ((UINT64)PcdGet32 (PcdFdBaseAddress) + (UINT64)PcdGet32
> (PcdFdSize) <= NewBase
> +          || (UINT64)PcdGet32 (PcdFdBaseAddress) >= NewBase +
> NewSize);
> +}
> +
> +VOID
> +ArmPlatformGetPlatformPpiList (
> +  OUT UINTN                   *PpiListSize,
> +  OUT EFI_PEI_PPI_DESCRIPTOR  **PpiList
> +  )
> +{
> +  *PpiListSize = 0;
> +  *PpiList = NULL;
> +}
> diff --git
> a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64Virtualization
> LibKVM/KVMHelper.S
> b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64Virtualization
> LibKVM/KVMHelper.S
> new file mode 100644
> index 000000000000..af028038b4a6
> --- /dev/null
> +++
> b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64Virtualization
> LibKVM/KVMHelper.S
> @@ -0,0 +1,86 @@
> +#
> +#  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_EXPORT(ArmGetPhysAddrTop)
> +
> +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
> +
> +//EFI_PHYSICAL_ADDRESS
> +//GetPhysAddrTop (
> +//  VOID
> +//  );
> +ASM_PFX(ArmGetPhysAddrTop):
> +  mrs   x0, id_aa64mmfr0_el1
> +  adr   x1, .LPARanges
> +  and   x0, x0, #7
> +  ldrb  w1, [x1, x0]
> +  mov   x0, #1
> +  lsl   x0, x0, x1
> +  ret
> +.LPARanges:
> +  .byte 32, 36, 40, 42, 44, 48, -1, -1
> +
> +ASM_FUNCTION_REMOVE_IF_UNREFERENCED
> diff --git
> a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64Virtualization
> LibKVM/KVMMem.c
> b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64Virtualization
> LibKVM/KVMMem.c
> new file mode 100644
> index 000000000000..f1ea66468027
> --- /dev/null
> +++
> b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64Virtualization
> LibKVM/KVMMem.c
> @@ -0,0 +1,102 @@
> +/** @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
> +
> +EFI_PHYSICAL_ADDRESS
> +ArmGetPhysAddrTop (
> +  VOID
> +  );
> +
> +/**
> +  Return the Virtual Memory Map of your platform
> +
> +  This Virtual Memory Map is used by MemoryInitPei Module to
> initialize the MMU
> +  on your platform.
> +
> +  @param[out]   VirtualMemoryMap    Array of
> ARM_MEMORY_REGION_DESCRIPTOR
> +                                    describing a Physical-to-Virtual
> Memory
> +                                    mapping. This array must be ended
> by a
> +                                    zero-filled entry
> +
> +**/
> +VOID
> +ArmPlatformGetVirtualMemoryMap (
> +  IN ARM_MEMORY_REGION_DESCRIPTOR** VirtualMemoryMap
> +  )
> +{
> +  ARM_MEMORY_REGION_ATTRIBUTES  CacheAttributes;
> +  ARM_MEMORY_REGION_DESCRIPTOR  *VirtualMemoryTable;
> +
> +  ASSERT (VirtualMemoryMap != NULL);
> +
> +  VirtualMemoryTable = AllocatePages (EFI_SIZE_TO_PAGES (
> +                                     sizeof
> (ARM_MEMORY_REGION_DESCRIPTOR)
> +                                     *
> MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS));
> +  if (VirtualMemoryTable == NULL) {
> +    DEBUG ((EFI_D_ERROR, "%a: Error: Failed AllocatePages()\n",
> __FUNCTION__));
> +    return;
> +  }
> +
> +  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_INFO, "%a: Dumping System DRAM Memory Map:\n"
> +      "\tPhysicalBase: 0x%lX\n"
> +      "\tVirtualBase: 0x%lX\n"
> +      "\tLength: 0x%lX\n",
> +      __FUNCTION__,
> +      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       = ArmGetPhysAddrTop () -
> 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/AArch64Virtualization
> SysConfigLibKVM/AArch64VirtualizationSysConfigLibKVM.c
> b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64Virtualization
> SysConfigLibKVM/AArch64VirtualizationSysConfigLibKVM.c
> new file mode 100644
> index 000000000000..514d9358964c
> --- /dev/null
> +++
> b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64Virtualization
> SysConfigLibKVM/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/AArch64Virtualization
> SysConfigLibKVM/AArch64VirtualizationSysConfigLibKVM.inf
> b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64Virtualization
> SysConfigLibKVM/AArch64VirtualizationSysConfigLibKVM.inf
> new file mode 100644
> index 000000000000..d4a495147de5
> --- /dev/null
> +++
> b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64Virtualization
> SysConfigLibKVM/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/PlatformPei/PlatformP
> eiLib.c
> b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformP
> eiLib.c
> new file mode 100755
> index 000000000000..bb873f04e46d
> --- /dev/null
> +++
> b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformP
> eiLib.c
> @@ -0,0 +1,47 @@
> +/** @file
> +*
> +*  Copyright (c) 2011-2012, 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 <PiPei.h>
> +
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/ArmPlatformLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/HobLib.h>
> +#include <Library/PcdLib.h>
> +#include <libfdt.h>
> +
> +EFI_STATUS
> +EFIAPI
> +PlatformPeim (
> +  VOID
> +  )
> +{
> +  UINT64               Base;
> +  VOID                *NewBase;
> +  UINTN                FdtSize;
> +
> +  BuildFvHob (PcdGet32(PcdFvBaseAddress), PcdGet32(PcdFvSize));
> +
> +  Base = PcdGet64 (PcdDeviceTreeBaseAddress);
> +  FdtSize = fdt_totalsize ((VOID *)(UINTN)Base);
> +
> +  NewBase = AllocatePages (EFI_SIZE_TO_PAGES (FdtSize));
> +  ASSERT (NewBase != NULL);
> +
> +  CopyMem (NewBase, (VOID *)(UINTN)Base, FdtSize);
> +  PcdSet64 (PcdDeviceTreeBaseAddress, (UINT64)NewBase);
> +
> +  return EFI_SUCCESS;
> +}
> diff --git
> a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformP
> eiLib.inf
> b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformP
> eiLib.inf
> new file mode 100755
> index 000000000000..b1e8bc986efc
> --- /dev/null
> +++
> b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformP
> eiLib.inf
> @@ -0,0 +1,58 @@
> +#/** @file
> +#
> +#  Copyright (c) 2011-2012, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of
> the BSD License
> +#  which accompanies this distribution.  The full text of the license
> may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +#
> +#**/
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = ArmPlatformPeiLib
> +  FILE_GUID                      = 49d37060-70b5-11e0-aa2d-
> 0002a5d5c51b
> +  MODULE_TYPE                    = SEC
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = PlatformPeiLib
> +
> +[Sources]
> +  PlatformPeiLib.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  ArmPkg/ArmPkg.dec
> +  ArmPlatformPkg/ArmPlatformPkg.dec
> +
> +[LibraryClasses]
> +  DebugLib
> +  HobLib
> +  ArmPlatformLib
> +  FdtLib
> +
> +[Ppis]
> +  gEfiPeiMasterBootModePpiGuid                  # PPI ALWAYS_PRODUCED
> +  gEfiPeiBootInRecoveryModePpiGuid              # PPI
> SOMETIMES_PRODUCED
> +
> +[FixedPcd]
> +  gArmTokenSpaceGuid.PcdFdBaseAddress
> +  gArmTokenSpaceGuid.PcdFdSize
> +
> +  gArmTokenSpaceGuid.PcdFvBaseAddress
> +  gArmTokenSpaceGuid.PcdFvSize
> +
> +  gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize
> +  gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize
> +
> +[Pcd]
> +  gArmTokenSpaceGuid.PcdDeviceTreeBaseAddress
> +
> +[depex]
> +  gEfiPeiMemoryDiscoveredPpiGuid
> +
> diff --git
> a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetS
> ystemLib.c
> b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetS
> ystemLib.c
> new file mode 100644
> index 000000000000..a420591a8e9c
> --- /dev/null
> +++
> b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetS
> ystemLib.c
> @@ -0,0 +1,97 @@
> +/** @file
> +  Support ResetSystem Runtime call using PSCI hvc calls
> +
> +  Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
> +  Copyright (c) 2013, ARM Ltd. All rights reserved.<BR>
> +  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 <PiDxe.h>
> +
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/EfiResetSystemLib.h>
> +
> +VOID
> +ArmPsciSystemReset (
> +  VOID
> +  );
> +
> +VOID
> +ArmPsciSystemOff (
> +  VOID
> +  );
> +
> +/**
> +  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
> +  )
> +{
> +  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
> +    ArmPsciSystemReset ();
> +    break;
> +  case EfiResetShutdown:
> +    // Send a PSCI 0.2 SYSTEM_OFF command
> +    ArmPsciSystemOff ();
> +    break;
> +
> +  default:
> +    ASSERT (FALSE);
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  // We should never be here
> +  DEBUG ((EFI_D_ERROR, "%a: PSCI Reset failed\n", __FUNCTION__));
> +  CpuDeadLoop ();
> +  return EFI_UNSUPPORTED;
> +}
> +
> +/**
> +  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/ResetS
> ystemLib.inf
> b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetS
> ystemLib.inf
> new file mode 100644
> index 000000000000..ed25977ff349
> --- /dev/null
> +++
> b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetS
> ystemLib.inf
> @@ -0,0 +1,36 @@
> +#/** @file
> +# Reset System lib to make it easy to port new platforms
> +#
> +# Copyright (c) 2008, Apple Inc. All rights reserved.<BR>
> +#
> +#  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
> +  ResetSystemPsci.S | GCC
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  MdePkg/MdePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +
> +[LibraryClasses]
> +  IoLib
> +  DebugLib
> +  BaseLib
> diff --git
> a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetS
> ystemPsci.S
> b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetS
> ystemPsci.S
> new file mode 100644
> index 000000000000..988b0fdc41e4
> --- /dev/null
> +++
> b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetS
> ystemPsci.S
> @@ -0,0 +1,40 @@
> +/** @file
> +  Support ResetSystem Runtime call using PSCI hvc calls
> +
> +  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 <AsmMacroIoLibV8.h>
> +#include <Base.h>
> +#include <Library/ArmLib.h>
> +#include <AutoGen.h>
> +
> +#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)
> +
> +.text
> +.align 2
> +
> +GCC_ASM_EXPORT(ArmPsciSystemOff)
> +GCC_ASM_EXPORT(ArmPsciSystemReset)
> +
> +ASM_PFX(ArmPsciSystemOff):
> +  ldr    w0, =PSCI_0_2_FN_SYSTEM_OFF
> +  hvc    #0
> +  ret
> +
> +ASM_PFX(ArmPsciSystemReset):
> +  ldr    w0, =PSCI_0_2_FN_SYSTEM_RESET
> +  hvc    #0
> +  ret
> --
> 1.8.3.2
> 





------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Peter Maydell Aug. 27, 2014, 6:17 p.m. UTC | #2
On 27 August 2014 19:15, Olivier Martin <olivier.martin@arm.com> wrote:
> I have been through the patchset yet. But I noticed the name of the platform
> in another email.
> Is this new platform AArch64 specific? Could we imagine this platform being
> easily ported to ARMv7 (with Virtualization extension)?

No, it's not 64-bit specific. QEMU supports this same board model
for both 64-bit and 32-bit CPU types, and we're expecting it to be
used for both with KVM.

-- PMM

------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Ard Biesheuvel Aug. 27, 2014, 7:02 p.m. UTC | #3
On 27 August 2014 20:17, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 27 August 2014 19:15, Olivier Martin <olivier.martin@arm.com> wrote:
>> I have been through the patchset yet. But I noticed the name of the platform
>> in another email.
>> Is this new platform AArch64 specific? Could we imagine this platform being
>> easily ported to ARMv7 (with Virtualization extension)?
>
> No, it's not 64-bit specific. QEMU supports this same board model
> for both 64-bit and 32-bit CPU types, and we're expecting it to be
> used for both with KVM.
>

You are right. I inherited the name from Michael Casadevall, and did
not give it any more thought, but in fact, there is very little code
in there that is specific to AArch64

I will change the names when I spin a v4.
Laszlo Ersek Aug. 27, 2014, 7:29 p.m. UTC | #4
On 08/27/14 21:02, Ard Biesheuvel wrote:
> On 27 August 2014 20:17, Peter Maydell <peter.maydell@linaro.org> wrote:
>> On 27 August 2014 19:15, Olivier Martin <olivier.martin@arm.com> wrote:
>>> I have been through the patchset yet. But I noticed the name of the platform
>>> in another email.
>>> Is this new platform AArch64 specific? Could we imagine this platform being
>>> easily ported to ARMv7 (with Virtualization extension)?
>>
>> No, it's not 64-bit specific. QEMU supports this same board model
>> for both 64-bit and 32-bit CPU types, and we're expecting it to be
>> used for both with KVM.
>>
> 
> You are right. I inherited the name from Michael Casadevall, and did
> not give it any more thought, but in fact, there is very little code
> in there that is specific to AArch64
> 
> I will change the names when I spin a v4.

Please skim the UINTN variables too, I vaguely remember that at some
point in my earlier review I said "this is OK because the code is 64-bit
only".

... It might have been in relation to DEBUGs and their format strings.
The general rule for printing an UINTN in code that can be both 32-bit
and 64-bit is to always cast it to UINT64 explicitly, and use %Lx. When
padding to a specific field width, say 016.

(
The conversion specifiers in edk2 DEBUGs have a few quirks. For example,
you can't print *all* unsigned integers in *decimal*; there's no %u
support. You can only print the full range of unsigned integer types in
hex (%x, %Lx). There's one "trick" for UINT32 though: you can cast such
to INT64 losslessly, then print them with %Ld, in decimal. But there is
no decimal support for the full range of UINT64.

Another quirk is that the "L" (and "l") modifiers don't stand for
"long", they mean "64-bit", even in ILP32 builds. That's why I always
use "L" rather than "l" for UINT64 / INT64: "L" doesn't exist in
standard C, nor in POSIX, for integers, hence it stands out from the
edk2 source as a non-portable length modifier.
)

Thanks
Laszlo


------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Laszlo Ersek Aug. 27, 2014, 10:43 p.m. UTC | #5
Some comments below

On 08/27/14 17:12, 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                  | 222 ++++++++++++++
>  .../AArch64Virtualization-KVM.fdf                  | 307 +++++++++++++++++++
>  .../AArch64Virtualization.dsc.inc                  | 336 +++++++++++++++++++++
>  .../AArch64VirtualizationPkg/Driver/VirtFdt.inf    |  61 ++++
>  .../AArch64VirtualizationPkg/Driver/VirtFdtDxe.c   | 249 +++++++++++++++
>  .../Include/Platform/KVM/ArmPlatform.h             |  27 ++
>  .../AArch64VirtualizationLibKVM/AArch64KVMLib.inf  |  57 ++++
>  .../Library/AArch64VirtualizationLibKVM/KVM.c      | 143 +++++++++
>  .../AArch64VirtualizationLibKVM/KVMHelper.S        |  86 ++++++
>  .../Library/AArch64VirtualizationLibKVM/KVMMem.c   | 102 +++++++
>  .../AArch64VirtualizationSysConfigLibKVM.c         |  95 ++++++
>  .../AArch64VirtualizationSysConfigLibKVM.inf       |  35 +++
>  .../Library/PlatformPei/PlatformPeiLib.c           |  47 +++
>  .../Library/PlatformPei/PlatformPeiLib.inf         |  58 ++++
>  .../Library/ResetSystemLib/ResetSystemLib.c        |  97 ++++++
>  .../Library/ResetSystemLib/ResetSystemLib.inf      |  36 +++
>  .../Library/ResetSystemLib/ResetSystemPsci.S       |  40 +++
>  17 files changed, 1998 insertions(+)

First of all, this ginormous patch should be split up in several smaller
ones. I apologize for requesting this only now, at v3.

edk2 is very modular, and this patch dumps 5 (FIVE) modules at once at
the poor reviewer. It is impenetrable, and the granularity of any
Acked-by or Reviewed-by is very bad -- you can't carry an A-b or an R-b
forward that has been given only for one module among the five.

So let's see:

>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization-KVM.dsc
>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization-KVM.fdf
>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization.dsc.inc

Please include these in a zeroth patch. It's not a requirement that
AArch64VirtualizationPkg be buildable at each stage, during bisection --
for example, it's not buildable before you introduce it *at all*. If it
isn't too hard, please shave these off to a separate patch.

>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdt.inf
>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdtDxe.c

This should be module #1.

>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Include/Platform/KVM/ArmPlatform.h

Yikes. After a while I managed to understand the dependency that this
header file resolves. Please make it a separate patch. Can be an early
one.

>  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

Module #2.

>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationSysConfigLibKVM/AArch64VirtualizationSysConfigLibKVM.c
>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationSysConfigLibKVM/AArch64VirtualizationSysConfigLibKVM.inf

Module #3.

>  create mode 100755 ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformPeiLib.c
>  create mode 100755 ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformPeiLib.inf

Module #4.

>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.c
>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.inf
>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemPsci.S

Module #5.

If I'm counting right, that's 7 new patches, in place of this huge one.
Five module patches, one patch for the header file, and one patch for
the DSC / FDF / etc meta files.

The module patches should be ordered logically, if such a logical
ordering exists.

Right now I'll try to review "Library/PlatformPei" and "Driver/". Some
of the modules added here I probably won't ever review (due to lack of
architectural knowledge).

> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformPeiLib.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformPeiLib.c

Directories holding library instances should have basename WhateverLib.
Hence, "Library/PlatformPeiLib".

> new file mode 100755
> index 000000000000..bb873f04e46d
> --- /dev/null
> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformPeiLib.c
> @@ -0,0 +1,47 @@
> +/** @file
> +*
> +*  Copyright (c) 2011-2012, 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 <PiPei.h>
> +
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/ArmPlatformLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/HobLib.h>
> +#include <Library/PcdLib.h>
> +#include <libfdt.h>
> +
> +EFI_STATUS
> +EFIAPI
> +PlatformPeim (
> +  VOID
> +  )
> +{
> +  UINT64               Base;
> +  VOID                *NewBase;

The asterisk should line up with "Base" above. Don't ask. :)

> +  UINTN                FdtSize;
> +
> +  BuildFvHob (PcdGet32(PcdFvBaseAddress), PcdGet32(PcdFvSize));

Okay, this has been preserved from the thus far only PlatformPeim()
implementation, in "ArmPlatformPkg/PlatformPei/PlatformPeiLib.c". Good.

> +
> +  Base = PcdGet64 (PcdDeviceTreeBaseAddress);

OK, I can see this dynamic PCD gets 0x40000000 as default value in the
DSC.

> +  FdtSize = fdt_totalsize ((VOID *)(UINTN)Base);
> +
> +  NewBase = AllocatePages (EFI_SIZE_TO_PAGES (FdtSize));
> +  ASSERT (NewBase != NULL);
> +
> +  CopyMem (NewBase, (VOID *)(UINTN)Base, FdtSize);
> +  PcdSet64 (PcdDeviceTreeBaseAddress, (UINT64)NewBase);
> +
> +  return EFI_SUCCESS;
> +}

Looks okay to me. Please consider logging an EFI_D_INFO message here, so
that we can feel warm and fuzzy about the DTB's copy being in permanent
PEI RAM. Something like:

  DEBUG ((EFI_D_INFO, "%a: copied DTB of size 0x%Lx to address %p\n",
    __FUNCTION__, (UINT64)FdtSize, NewBase));

You can ignore this if you want to.

> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformPeiLib.inf b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformPeiLib.inf
> new file mode 100755
> index 000000000000..b1e8bc986efc
> --- /dev/null
> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformPeiLib.inf
> @@ -0,0 +1,58 @@
> +#/** @file
> +#
> +#  Copyright (c) 2011-2012, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD License
> +#  which accompanies this distribution.  The full text of the license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +#
> +#**/
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = ArmPlatformPeiLib

This should say "PlatformPeiLib" (after you rename the containing
directory to PlatformPeiLib).

> +  FILE_GUID                      = 49d37060-70b5-11e0-aa2d-0002a5d5c51b

Please don't forget to update the FILE_GUID with "uuidgen" each time you
introduce a new INF file. The GUID visible above is from
"ArmPlatformPkg/PlatformPei/PlatformPeiLib.inf".

> +  MODULE_TYPE                    = SEC
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = PlatformPeiLib
> +
> +[Sources]
> +  PlatformPeiLib.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  ArmPkg/ArmPkg.dec
> +  ArmPlatformPkg/ArmPlatformPkg.dec

You can most likely drop a few false package dependencies here, but it's
not a requirement.

> +
> +[LibraryClasses]
> +  DebugLib
> +  HobLib
> +  ArmPlatformLib
> +  FdtLib

MemoryAllocationLib is missing (probably inherited anyway through one of
these); ArmPlatformLib and HobLib look superfluous. Saying just for
pedantry.

> +
> +[Ppis]
> +  gEfiPeiMasterBootModePpiGuid                  # PPI ALWAYS_PRODUCED
> +  gEfiPeiBootInRecoveryModePpiGuid              # PPI SOMETIMES_PRODUCED

Ugh, no, I don't think so. The *library* doesn't produce these.

> +
> +[FixedPcd]
> +  gArmTokenSpaceGuid.PcdFdBaseAddress
> +  gArmTokenSpaceGuid.PcdFdSize
> +
> +  gArmTokenSpaceGuid.PcdFvBaseAddress
> +  gArmTokenSpaceGuid.PcdFvSize
> +
> +  gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize
> +  gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize
> +

All of these should be removed.

> +[Pcd]
> +  gArmTokenSpaceGuid.PcdDeviceTreeBaseAddress

Yes, we need this.

> +
> +[depex]
> +  gEfiPeiMemoryDiscoveredPpiGuid
> +

Nice! You didn't forget about this dependency. The AllocatePages() call
in the C file *must* be served from permanent PEI RAM. Good.

> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdt.inf b/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdt.inf
> new file mode 100644
> index 000000000000..464829607871
> --- /dev/null
> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdt.inf
> @@ -0,0 +1,61 @@
> +## @file
> +#  Device tree enumeration DXE driver for AArch64 VMs

The AArch64 reference should probably be generalized.

> +#
> +#  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]

Please drop this empty section.

> +
> +[Pcd]
> +  gArmTokenSpaceGuid.PcdSystemMemoryBase

This PCD is no longer needed.

> +  gArmTokenSpaceGuid.PcdGicDistributorBase
> +  gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
> +  gArmTokenSpaceGuid.PcdArmArchTimerSecIntrNum
> +  gArmTokenSpaceGuid.PcdArmArchTimerIntrNum
> +  gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum
> +  gArmTokenSpaceGuid.PcdArmArchTimerHypIntrNum
> +  gArmPlatformTokenSpaceGuid.PcdPL031RtcBase
> +  gArmTokenSpaceGuid.PcdDeviceTreeBaseAddress
> +
> +[Protocols]
> +

Strictly speaking, you might want to list gEfiDevicePathProtocolGuid
here, but stuff will work anyway.

> +[Depex]
> +  TRUE

> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdtDxe.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdtDxe.c
> new file mode 100644
> index 000000000000..1ad9e929ae62
> --- /dev/null
> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdtDxe.c
> @@ -0,0 +1,249 @@
> +/** @file
> +*  Device tree enumeration DXE driver for AArch64 VMs

AArch64 reference

> +*
> +*  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>
> +
> +CONST UINT32 mUint32Max = 0xFFFFFFFFU;
> +
> +#pragma pack (1)
> +typedef struct {
> +  VENDOR_DEVICE_PATH                  Vendor;
> +  UINT64                              PhysBase;
> +  EFI_DEVICE_PATH_PROTOCOL            End;
> +} VIRTIO_TRANSPORT_DEVICE_PATH;
> +#pragma pack ()

Thanks!

> +
> +typedef enum {
> +  PropertyTypeUnknown,
> +  PropertyTypeGic,
> +  PropertyTypeRtc,
> +  PropertyTypeVirtio,
> +  PropertyTypeUart,
> +  PropertyTypeTimer,
> +} PROPERTY_TYPE;

Thanks!

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

Thanks!

> +
> +STATIC CONST PROPERTY CompatibleProperties[] = {
> +  { PropertyTypeGic,     "arm,cortex-a15-gic"  },
> +  { PropertyTypeRtc,     "arm,pl031"           },
> +  { PropertyTypeVirtio,  "virtio,mmio"         },
> +  { PropertyTypeUart,    "arm,pl011"           },
> +  { PropertyTypeTimer,   "arm,armv7-timer"     },
> +  { PropertyTypeTimer,   "arm,armv8-timer"     },
> +  { PropertyTypeUnknown, ""                    }
> +};
> +
> +typedef struct {
> +  UINT32  Type;
> +  UINT32  Number;
> +  UINT32  Flags;
> +} INTERRUPT_PROP;
> +
> +STATIC
> +PROPERTY_TYPE
> +GetTypeFromNode (
> +  IN CONST CHAR8 *NodeType,
> +  IN UINTN       Size
> +  )
> +{
> +  CONST CHAR8 *Compatible;
> +
> +  //
> +  // A 'compatible' node may contain a sequence of NULL terminated
> +  // compatible strings so check each one
> +  //
> +  for (Compatible = NodeType; Compatible < NodeType + Size && *Compatible;
> +       Compatible += 1 + AsciiStrLen (Compatible)) {
> +
> +    CONST PROPERTY *CompProp;
> +
> +    for (CompProp = CompatibleProperties; CompProp->Compatible[0]; CompProp++) {
> +      if (AsciiStrCmp (CompProp->Compatible, Compatible) == 0) {
> +        return CompProp->Type;
> +      }
> +    }
> +  }
> +  return PropertyTypeUnknown;
> +}

Thanks!

> +
> +EFI_STATUS
> +EFIAPI
> +InitializeVirtFdtDxe (
> +  IN EFI_HANDLE           ImageHandle,
> +  IN EFI_SYSTEM_TABLE     *SystemTable
> +  )
> +{
> +  VOID        *DeviceTreeBase;

(Please line up the asterisk with Node below.)

> +  INT32        Node, Prev;
> +  EFI_STATUS   Status;
> +
> +  DeviceTreeBase = (VOID *)PcdGet64 (PcdDeviceTreeBaseAddress);
> +  ASSERT (DeviceTreeBase != NULL);

This assert will be trivially true, since the DSC-default value of the
PCD is 0x4000_0000.

It might make sense to preserve PcdSystemMemoryBase after all, in the
INF file, and here assert that DeviceTreeBase is unequal to
PcdSystemMemoryBase. If you agree.

> +
> +  if (fdt_check_header (DeviceTreeBase) != 0) {
> +    DEBUG ((EFI_D_ERROR, "%a: No DTB found @ 0x%Lx\n", __FUNCTION__, DeviceTreeBase));

%p for (VOID*), please

> +    return EFI_NOT_FOUND;
> +  }
> +
> +  Status = gBS->InstallConfigurationTable (&gFdtTableGuid, DeviceTreeBase);
> +  ASSERT_EFI_ERROR (Status);

Okay.

> +
> +  DEBUG ((EFI_D_INFO, "%a: DTB @ 0x%p\n", __FUNCTION__, DeviceTreeBase));

Looks good, thanks.

> +
> +  //
> +  // Now enumerate the nodes and install peripherals that we are interested in,
> +  // i.e., GIC, RTC and virtio MMIO nodes
> +  //
> +  for (Prev = 0;; Prev = Node) {
> +    CONST CHAR8                   *Type;
> +    INT32                          Len;
> +    PROPERTY_TYPE                  PropType;
> +    CONST VOID                    *RegProp;
> +    VIRTIO_TRANSPORT_DEVICE_PATH  *DevicePath;
> +    EFI_HANDLE                     Handle;
> +    UINT64                         RegBase;
> +    UINT64                         DistBase, CpuBase;
> +    CONST INTERRUPT_PROP          *InterruptProp;
> +    INT32                          SecIntrNum, IntrNum, VirtIntrNum, HypIntrNum;

(please line up the asterisks if you care enough :))

> +
> +    Node = fdt_next_node (DeviceTreeBase, Prev, NULL);
> +    if (Node < 0)
> +      break;

braces

> +
> +    Type = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len);
> +    if (Type == NULL)
> +      continue;

braces

> +
> +    PropType = GetTypeFromNode (Type, Len);
> +    if (PropType == PropertyTypeUnknown)
> +      continue;

braces

> +
> +    //
> +    // 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 (DeviceTreeBase, Node, "reg", &Len);
> +    ASSERT (RegProp != NULL || PropType == PropertyTypeTimer);
> +
> +    switch (PropType) {
> +
> +    case PropertyTypeVirtio:
> +      ASSERT (Len == 16);
> +      //
> +      // Create a unique device path for this transport on the fly
> +      //
> +      RegBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);
> +      DevicePath = (VIRTIO_TRANSPORT_DEVICE_PATH *)CreateDeviceNode (
> +                                    HARDWARE_DEVICE_PATH,
> +                                    HW_VENDOR_DP,
> +                                    sizeof (VIRTIO_TRANSPORT_DEVICE_PATH));
> +
> +      CopyMem (&DevicePath->Vendor.Guid, &gEfiCallerIdGuid, sizeof (EFI_GUID));
> +      DevicePath->PhysBase = RegBase;
> +      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, "%a: Failed to install the EFI_DEVICE_PATH protocol on a new handle\n",
> +               __FUNCTION__));
> +        break;
> +      }

OK, thanks. No need to update this, just two generic hints:
- lines shorter than 80 chars are preferred,
- the format specifier %r formats values of type EFI_STATUS and
  RETURN_STATUS to textual representation.

> +
> +      Status = VirtioMmioInstallDevice (RegBase, Handle);
> +      if (EFI_ERROR (Status))
> +        DEBUG ((EFI_D_ERROR, "%a: Failed to install VirtIO transport @ 0x%Lx on handle %p\n",
> +                __FUNCTION__, RegBase, Handle));

braces, please.

Also, if VirtioMmioInstallDevice() fails, we shouldn't leak the
just-created handle with the devpath protocol instance on it. Please
uninstall that protocol here, in the error branch, and then the handle
itself will go away. See UninstallProtocolInterface() in the UEFI spec:
"If the last protocol interface is removed from a handle, the handle is
freed and is no longer valid."

I apologize for noticing this only now; I was very tired when I looked
at the last version of this code.


> +      break;
> +
> +    case PropertyTypeGic:
> +      ASSERT (Len == 32);
> +
> +      DistBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);
> +      CpuBase = fdt64_to_cpu (((UINT64 *)RegProp)[2]);
> +      ASSERT (DistBase < mUint32Max);
> +      ASSERT (CpuBase < mUint32Max);

less-than-or-equal, but it makes no difference in practice, since these
base addresses can't point to single-byte "things". You're erring on the
safe side. Thanks for adding the asserts!

> +
> +      PcdSet32 (PcdGicDistributorBase, (UINT32)DistBase);
> +      PcdSet32 (PcdGicInterruptInterfaceBase, (UINT32)CpuBase);
> +
> +      DEBUG ((EFI_D_INFO, "Found GIC @ 0x%x/0x%x\n", DistBase, CpuBase));

But here you should use %Lx, these are UINT64's.

> +      break;
> +
> +    case PropertyTypeRtc:
> +      ASSERT (Len == 16);
> +
> +      RegBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);
> +      ASSERT (RegBase < mUint32Max);
> +
> +      PcdSet32 (PcdPL031RtcBase, (UINT32)RegBase);
> +
> +      DEBUG ((EFI_D_INFO, "Found PL031 RTC @ 0x%x\n", RegBase));

%Lx

> +      break;
> +
> +    case PropertyTypeTimer:
> +
> +      //
> +      // - interrupts : Interrupt list for secure, non-secure, virtual and
> +      //  hypervisor timers, in that order.
> +      //
> +      InterruptProp = fdt_getprop (DeviceTreeBase, Node, "interrupts", &Len);
> +      ASSERT (Len == 48);
> +
> +      SecIntrNum = fdt32_to_cpu (InterruptProp[0].Number)
> +                   + (InterruptProp[0].Type ? 16 : 0);
> +      IntrNum = fdt32_to_cpu (InterruptProp[1].Number)
> +                + (InterruptProp[1].Type ? 16 : 0);
> +      VirtIntrNum = fdt32_to_cpu (InterruptProp[2].Number)
> +                    + (InterruptProp[2].Type ? 16 : 0);
> +      HypIntrNum = fdt32_to_cpu (InterruptProp[3].Number)
> +                   + (InterruptProp[3].Type ? 16 : 0);
> +
> +      DEBUG ((EFI_D_INFO, "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;
> +}

Looks good otherwise; thanks!

Laszlo

------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Laszlo Ersek Aug. 27, 2014, 10:55 p.m. UTC | #6
On 08/27/14 17:12, Ard Biesheuvel wrote:

>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdt.inf
>  create mode 100644 ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdtDxe.c

sorry, forgot to say: please rename the Driver pathname component (the
directory name) to VirtFdtDxe.

Thanks
Laszlo


------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Laszlo Ersek Aug. 28, 2014, 10:39 a.m. UTC | #7
On 08/27/14 17:12, Ard Biesheuvel wrote:

> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Include/Platform/KVM/ArmPlatform.h b/ArmPlatformPkg/AArch64VirtualizationPkg/Include/Platform/KVM/ArmPlatform.h
> new file mode 100644
> index 000000000000..5a74456d123e
> --- /dev/null
> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Include/Platform/KVM/ArmPlatform.h
> @@ -0,0 +1,27 @@
> +/** @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
> +
> +#endif

When you split this out in a separate patch, you can add my

Acked-by: Laszlo Ersek <lersek@redhat.com>

to it.

Thanks,
Laszlo


------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Laszlo Ersek Aug. 28, 2014, 10:46 a.m. UTC | #8
On 08/27/14 17:12, Ard Biesheuvel wrote:

> 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

AArch64 reference

> +#  
> +#  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

base name should preferably end with Lib, *and* match the basename of
the containing directory

> +  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

When you split this out into a separate patch, you can add my

Acked-by: Laszlo Ersek <lersek@redhat.com>

to it. This module is a no-op library instance, basically.

It's also correctly used to resolve the library class in the DSC.

It would be nice to clean up BASE_NAME etc, but I don't want to drive
you mad. :) Can be done incrementally later, if anyone cares.

Thanks,
Laszlo


------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Ard Biesheuvel Aug. 28, 2014, 10:53 a.m. UTC | #9
On 28 August 2014 12:46, Laszlo Ersek <lersek@redhat.com> wrote:
> On 08/27/14 17:12, Ard Biesheuvel wrote:
>
>> 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
>
> AArch64 reference
>
>> +#
>> +#  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
>
> base name should preferably end with Lib, *and* match the basename of
> the containing directory
>
>> +  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
>
> When you split this out into a separate patch, you can add my
>
> Acked-by: Laszlo Ersek <lersek@redhat.com>
>
> to it. This module is a no-op library instance, basically.
>
> It's also correctly used to resolve the library class in the DSC.
>
> It would be nice to clean up BASE_NAME etc, but I don't want to drive
> you mad. :) Can be done incrementally later, if anyone cares.
>

Don't worry, keep it coming. I am refactoring all of it, basically,
renaming and moving stuff around, and I had in fact already updated
this particular BASE_NAME.
Laszlo Ersek Aug. 28, 2014, 10:55 a.m. UTC | #10
On 08/27/14 17:12, Ard Biesheuvel wrote:

> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.c
> new file mode 100644
> index 000000000000..a420591a8e9c
> --- /dev/null
> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.c
> @@ -0,0 +1,97 @@
> +/** @file
> +  Support ResetSystem Runtime call using PSCI hvc calls
> +
> +  Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
> +  Copyright (c) 2013, ARM Ltd. All rights reserved.<BR>
> +  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 <PiDxe.h>
> +
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/EfiResetSystemLib.h>
> +
> +VOID
> +ArmPsciSystemReset (
> +  VOID
> +  );
> +
> +VOID
> +ArmPsciSystemOff (
> +  VOID
> +  );
> +
> +/**
> +  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
> +  )
> +{
> +  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
> +    ArmPsciSystemReset ();
> +    break;
> +  case EfiResetShutdown:
> +    // Send a PSCI 0.2 SYSTEM_OFF command
> +    ArmPsciSystemOff ();
> +    break;
> +
> +  default:
> +    ASSERT (FALSE);
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  // We should never be here
> +  DEBUG ((EFI_D_ERROR, "%a: PSCI Reset failed\n", __FUNCTION__));
> +  CpuDeadLoop ();
> +  return EFI_UNSUPPORTED;
> +}
> +
> +/**
> +  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..ed25977ff349
> --- /dev/null
> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.inf
> @@ -0,0 +1,36 @@
> +#/** @file
> +# Reset System lib to make it easy to port new platforms
> +#
> +# Copyright (c) 2008, Apple Inc. All rights reserved.<BR>
> +#
> +#  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
> +  ResetSystemPsci.S | GCC
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  MdePkg/MdePkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +
> +[LibraryClasses]
> +  IoLib
> +  DebugLib
> +  BaseLib

> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemPsci.S b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemPsci.S
> new file mode 100644
> index 000000000000..988b0fdc41e4
> --- /dev/null
> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemPsci.S
> @@ -0,0 +1,40 @@
> +/** @file
> +  Support ResetSystem Runtime call using PSCI hvc calls
> +
> +  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 <AsmMacroIoLibV8.h>
> +#include <Base.h>
> +#include <Library/ArmLib.h>
> +#include <AutoGen.h>
> +
> +#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)
> +
> +.text
> +.align 2
> +
> +GCC_ASM_EXPORT(ArmPsciSystemOff)
> +GCC_ASM_EXPORT(ArmPsciSystemReset)
> +
> +ASM_PFX(ArmPsciSystemOff):
> +  ldr    w0, =PSCI_0_2_FN_SYSTEM_OFF
> +  hvc    #0
> +  ret
> +
> +ASM_PFX(ArmPsciSystemReset):
> +  ldr    w0, =PSCI_0_2_FN_SYSTEM_RESET
> +  hvc    #0
> +  ret
> 

Can't verify the ARM specifics, but structurally it looks sane. It
resolves the library class defined in "EmbeddedPkg/EmbeddedPkg.dec",
header file being in "EmbeddedPkg/Include/Library/EfiResetSystemLib.h".

For this module-to-be:

Acked-by: Laszlo Ersek <lersek@redhat.com>

Thanks
Laszlo

------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Laszlo Ersek Aug. 28, 2014, 12:03 p.m. UTC | #11
comments below

On 08/27/14 17:12, Ard Biesheuvel wrote:

> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/AArch64KVMLib.inf b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/AArch64KVMLib.inf
> new file mode 100644
> index 000000000000..b30d70f3a1ed
> --- /dev/null
> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/AArch64KVMLib.inf
> @@ -0,0 +1,57 @@
> +#/* @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

BASE_NAME and containing directory name should be cleaned up, plus
perhaps Aarch64 reference should be generalized

> +  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
> +  gArmPlatformTokenSpaceGuid.PcdSystemMemoryInitializeInSec
> +
> +[Pcd]
> +  gArmTokenSpaceGuid.PcdSystemMemoryBase
> +  gArmTokenSpaceGuid.PcdSystemMemorySize
> +  gArmTokenSpaceGuid.PcdDeviceTreeBaseAddress
> +
> +[FixedPcd]
> +  gArmTokenSpaceGuid.PcdArmPrimaryCoreMask
> +  gArmTokenSpaceGuid.PcdArmPrimaryCore
> +
> +  gArmPlatformTokenSpaceGuid.PcdCoreCount
> +  gArmTokenSpaceGuid.PcdFdBaseAddress
> +  gArmTokenSpaceGuid.PcdFdSize

> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVM.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVM.c
> new file mode 100644
> index 000000000000..cd9edfe5138b
> --- /dev/null
> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVM.c
> @@ -0,0 +1,143 @@
> +/** @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;
> +}

Yes, this seems sane.

> +
> +/**
> +  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
> +  )
> +{
> +  //
> +  // We are relying on ArmPlatformInitializeSystemMemory () being called from
> +  // InitializeMemory (), which only occurs if the following feature is disabled
> +  //
> +  ASSERT (!FeaturePcdGet (PcdSystemMemoryInitializeInSec));
> +  return RETURN_SUCCESS;
> +}

Great; we agreed upon this in
<http://thread.gmane.org/gmane.comp.bios.tianocore.devel/8969/focus=9040>.
Thanks.

> +
> +/**
> +  Initialize the system (or sometimes called permanent) memory
> +
> +  This memory is generally represented by the DRAM.
> +
> +**/
> +VOID
> +ArmPlatformInitializeSystemMemory (
> +  VOID
> +  )
> +{
> +  VOID   *DeviceTreeBase;
> +  INT32   Node, Prev;
> +  UINT64  NewBase = 0;
> +  UINT64  NewSize = 0;

Initialization of auto variables is frowned upon in edk2; please use
separate assignments.

> +
> +  DeviceTreeBase = (VOID *)PcdGet64 (PcdDeviceTreeBaseAddress);

I suggest an intervening (UINTN) cast here, otherwise you might get
warnings in a 32-bit build.

> +  ASSERT (DeviceTreeBase != NULL);

In the hope that I'm not suggesting something insane, you might also
want to assert at this point that PcdDeviceTreeBaseAddress equals
PcdSystemMemoryBase.

> +
> +  //
> +  // Make sure we have a valid device tree blob at the base of DRAM
> +  //
> +  if (fdt_check_header (DeviceTreeBase) != 0)
> +    return;

I believe this should be asserted instead. If this fails, we're doomed.

> +
> +  //
> +  // Look for a memory node
> +  // TODO handle disjoint memory
> +  //

Please drop the TODO; I don't think we want to handle disjoint memory
very soon, and even then it would take more intrusive changes than what
is marked here, locally, with this comment.

> +  for (Prev = 0;; Prev = Node) {
> +    CONST CHAR8  *Type;
> +    INT32         Len;
> +
> +    Node = fdt_next_node (DeviceTreeBase, Prev, NULL);
> +    if (Node < 0)
> +      return;

Braces. Also, I think we should rather break here, not return; the
ASSERT()s after the loop should run in either case. If we don't find any
good node, then the ASSERTs() should trigger.

> +
> +    Type = fdt_getprop (DeviceTreeBase, Node, "device_type", &Len);
> +    if (Type && AsciiStrnCmp (Type, "memory", Len) == 0) {
> +      CONST UINT64 *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

not sure if this TODO is up-to-date

> +      //
> +      RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);
> +      if (RegProp != 0 && Len == (2 * sizeof (UINT64))) {
> +
> +        NewBase = fdt64_to_cpu (RegProp[0]);
> +        NewSize = fdt64_to_cpu (RegProp[1]);
> +
> +        PcdSet64 (PcdSystemMemoryBase, NewBase);
> +        PcdSet64 (PcdSystemMemorySize, NewSize);

If I recall correctly, you had the idea that PcdSystemMemoryBase should
not change (ie. we should assert that), and I think I agreed... Hm...

Yes, it's in here:
<http://thread.gmane.org/gmane.comp.bios.tianocore.devel/8969/focus=9039>.
Search for "NewBase to be different from 0x4000_0000".

So please add that assert as well. (And, just to be fully safe, you
might consider turning PcdSystemMemoryBase into fixed-at-build again!)

> +
> +        DEBUG ((EFI_D_INFO, "KVM: System RAM @ 0x%lx - 0x%lx\n",
> +           NewBase, NewBase + NewSize - 1));
> +      } else {
> +        DEBUG ((EFI_D_ERROR, "KVM: Failed to parse FDT memory node\n"));
> +      }
> +      break;
> +    }
> +  }
> +  //
> +  // We need to make sure that the machine we are running on has at least
> +  // 128 MB of memory configured, and does not run from shadowed NOR. This

suggesting wording cleanup: "and is currently executing this binary from
NOR flash".

> +  // prevents the device tree at base of DRAM from getting clobbered before we

"... from getting clobbered [when our caller installs permanent PEI
RAM,] before ..."

> +  // have a chance of marking its location as reserved or moving it out of the
> +  // way.

... copy it to a freshly allocated block in the permanent PEI RAM in the
platform PEIM...

I think we can be specific.

> +  //
> +  ASSERT (NewSize >= SIZE_128MB);
> +  ASSERT ((UINT64)PcdGet32 (PcdFdBaseAddress) + (UINT64)PcdGet32 (PcdFdSize) <= NewBase
> +          || (UINT64)PcdGet32 (PcdFdBaseAddress) >= NewBase + NewSize);
> +}

Operator || should go to the end of the first line.

Also, edk2's line wrapping style prescribes one or two spaces
indentation, relative to the function's or macro's *name*, whose
argument list you are wrapping. Like this:

  ASSERT (
    ((UINT64)PcdGet32 (PcdFdBaseAddress) +
     (UINT64)PcdGet32 (PcdFdSize)) <= NewBase ||
    (UINT64)PcdGet32 (PcdFdBaseAddress) >= NewBase + NewSize);

Otherwise, this matches our discussion in the same message (linked
above), thanks!

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

I guess this is fine.

> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMHelper.S b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMHelper.S
> new file mode 100644
> index 000000000000..af028038b4a6
> --- /dev/null
> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMHelper.S
> @@ -0,0 +1,86 @@
> +#
> +#  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_EXPORT(ArmGetPhysAddrTop)
> +
> +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
> +
> +//EFI_PHYSICAL_ADDRESS
> +//GetPhysAddrTop (
> +//  VOID
> +//  );
> +ASM_PFX(ArmGetPhysAddrTop):
> +  mrs   x0, id_aa64mmfr0_el1
> +  adr   x1, .LPARanges
> +  and   x0, x0, #7
> +  ldrb  w1, [x1, x0]
> +  mov   x0, #1
> +  lsl   x0, x0, x1
> +  ret
> +.LPARanges:
> +  .byte 32, 36, 40, 42, 44, 48, -1, -1
> +
> +ASM_FUNCTION_REMOVE_IF_UNREFERENCED

This I can't validate...

> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMMem.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMMem.c
> new file mode 100644
> index 000000000000..f1ea66468027
> --- /dev/null
> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMMem.c
> @@ -0,0 +1,102 @@
> +/** @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
> +
> +EFI_PHYSICAL_ADDRESS
> +ArmGetPhysAddrTop (
> +  VOID
> +  );
> +
> +/**
> +  Return the Virtual Memory Map of your platform
> +
> +  This Virtual Memory Map is used by MemoryInitPei Module to initialize the MMU
> +  on your platform.
> +
> +  @param[out]   VirtualMemoryMap    Array of ARM_MEMORY_REGION_DESCRIPTOR 
> +                                    describing a Physical-to-Virtual Memory
> +                                    mapping. This array must be ended by a
> +                                    zero-filled entry
> +
> +**/
> +VOID
> +ArmPlatformGetVirtualMemoryMap (
> +  IN ARM_MEMORY_REGION_DESCRIPTOR** VirtualMemoryMap
> +  )
> +{
> +  ARM_MEMORY_REGION_ATTRIBUTES  CacheAttributes;
> +  ARM_MEMORY_REGION_DESCRIPTOR  *VirtualMemoryTable;
> +
> +  ASSERT (VirtualMemoryMap != NULL);
> +
> +  VirtualMemoryTable = AllocatePages (EFI_SIZE_TO_PAGES (
> +                                     sizeof (ARM_MEMORY_REGION_DESCRIPTOR)
> +                                     * MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS));

The utterly pedantic formatting would be

VirtualMemoryTable = AllocatePages (
                       EFI_SIZE_TO_PAGES (
                         sizeof (ARM_MEMORY_REGION_DESCRIPTOR) *
                         MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS)
                         )
                       );

I leave it to you...

> +  if (VirtualMemoryTable == NULL) {
> +    DEBUG ((EFI_D_ERROR, "%a: Error: Failed AllocatePages()\n", __FUNCTION__));
> +    return;
> +  }
> +
> +  if (FeaturePcdGet (PcdCacheEnable) == TRUE) {
> +      CacheAttributes = DDR_ATTRIBUTES_CACHED;
> +  } else {
> +      CacheAttributes = DDR_ATTRIBUTES_UNCACHED;
> +  }

Okay, we set this PCD to TRUE in the DSC.

> +
> +  // 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_INFO, "%a: Dumping System DRAM Memory Map:\n"
> +      "\tPhysicalBase: 0x%lX\n"
> +      "\tVirtualBase: 0x%lX\n"
> +      "\tLength: 0x%lX\n",
> +      __FUNCTION__,
> +      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       = ArmGetPhysAddrTop () - VirtualMemoryTable[2].PhysicalBase;
> +  VirtualMemoryTable[2].Attributes   = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
> +

Seems reasonable.

> +  // End of Table
> +  VirtualMemoryTable[3] = (ARM_MEMORY_REGION_DESCRIPTOR){};

Yikes! Edk2 coding style violation galore! :)
- Structure assignment!
- Compound literal!!
- GNUism in initializer list: {} -- meaning in fact { 0 }!!!

Please replace this with a simple ZeroMem() call.

> +
> +  *VirtualMemoryMap = VirtualMemoryTable;
> +}

Thanks!
Laszlo

------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Ard Biesheuvel Aug. 28, 2014, 12:50 p.m. UTC | #12
On 28 August 2014 14:03, Laszlo Ersek <lersek@redhat.com> wrote:
> comments below
>
> On 08/27/14 17:12, Ard Biesheuvel wrote:
>
>> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/AArch64KVMLib.inf b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/AArch64KVMLib.inf
>> new file mode 100644
>> index 000000000000..b30d70f3a1ed
>> --- /dev/null
>> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/AArch64KVMLib.inf
>> @@ -0,0 +1,57 @@
>> +#/* @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
>
> BASE_NAME and containing directory name should be cleaned up, plus
> perhaps Aarch64 reference should be generalized
>

OK, already part of my big refactor

>> +  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
>> +  gArmPlatformTokenSpaceGuid.PcdSystemMemoryInitializeInSec
>> +
>> +[Pcd]
>> +  gArmTokenSpaceGuid.PcdSystemMemoryBase
>> +  gArmTokenSpaceGuid.PcdSystemMemorySize
>> +  gArmTokenSpaceGuid.PcdDeviceTreeBaseAddress
>> +
>> +[FixedPcd]
>> +  gArmTokenSpaceGuid.PcdArmPrimaryCoreMask
>> +  gArmTokenSpaceGuid.PcdArmPrimaryCore
>> +
>> +  gArmPlatformTokenSpaceGuid.PcdCoreCount
>> +  gArmTokenSpaceGuid.PcdFdBaseAddress
>> +  gArmTokenSpaceGuid.PcdFdSize
>
>> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVM.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVM.c
>> new file mode 100644
>> index 000000000000..cd9edfe5138b
>> --- /dev/null
>> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVM.c
>> @@ -0,0 +1,143 @@
>> +/** @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;
>> +}
>
> Yes, this seems sane.
>
>> +
>> +/**
>> +  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
>> +  )
>> +{
>> +  //
>> +  // We are relying on ArmPlatformInitializeSystemMemory () being called from
>> +  // InitializeMemory (), which only occurs if the following feature is disabled
>> +  //
>> +  ASSERT (!FeaturePcdGet (PcdSystemMemoryInitializeInSec));
>> +  return RETURN_SUCCESS;
>> +}
>
> Great; we agreed upon this in
> <http://thread.gmane.org/gmane.comp.bios.tianocore.devel/8969/focus=9040>.
> Thanks.
>
>> +
>> +/**
>> +  Initialize the system (or sometimes called permanent) memory
>> +
>> +  This memory is generally represented by the DRAM.
>> +
>> +**/
>> +VOID
>> +ArmPlatformInitializeSystemMemory (
>> +  VOID
>> +  )
>> +{
>> +  VOID   *DeviceTreeBase;
>> +  INT32   Node, Prev;
>> +  UINT64  NewBase = 0;
>> +  UINT64  NewSize = 0;
>
> Initialization of auto variables is frowned upon in edk2; please use
> separate assignments.
>

OK

>> +
>> +  DeviceTreeBase = (VOID *)PcdGet64 (PcdDeviceTreeBaseAddress);
>
> I suggest an intervening (UINTN) cast here, otherwise you might get
> warnings in a 32-bit build.
>
>> +  ASSERT (DeviceTreeBase != NULL);
>
> In the hope that I'm not suggesting something insane, you might also
> want to assert at this point that PcdDeviceTreeBaseAddress equals
> PcdSystemMemoryBase.
>

I don't think it is necessary for this module to be that rigid.
In particular, now that we have PcdDeviceTreeBaseAddress, we can
define it in the DSC, and in QEMU's case, its default value will be
0x4000_0000.
Then, if you are using a slightly different flavor of emulation, it
would be perfectly legal to define this to point elsewhere (as long as
it points to where you are in fact putting the DTB). If this address
is not covered by system DRAM, that is perfectly fine. In fact, the
asserts should only fire if we detect here that
PcdDeviceTreeBaseAddress is in DRAM, and PlatformPeim() should only
perform the relocation under that condition as well.

>> +
>> +  //
>> +  // Make sure we have a valid device tree blob at the base of DRAM
>> +  //
>> +  if (fdt_check_header (DeviceTreeBase) != 0)
>> +    return;
>
> I believe this should be asserted instead. If this fails, we're doomed.
>

Agreed.

>> +
>> +  //
>> +  // Look for a memory node
>> +  // TODO handle disjoint memory
>> +  //
>
> Please drop the TODO; I don't think we want to handle disjoint memory
> very soon, and even then it would take more intrusive changes than what
> is marked here, locally, with this comment.
>

ok

>> +  for (Prev = 0;; Prev = Node) {
>> +    CONST CHAR8  *Type;
>> +    INT32         Len;
>> +
>> +    Node = fdt_next_node (DeviceTreeBase, Prev, NULL);
>> +    if (Node < 0)
>> +      return;
>
> Braces. Also, I think we should rather break here, not return; the
> ASSERT()s after the loop should run in either case. If we don't find any
> good node, then the ASSERTs() should trigger.
>
>> +
>> +    Type = fdt_getprop (DeviceTreeBase, Node, "device_type", &Len);
>> +    if (Type && AsciiStrnCmp (Type, "memory", Len) == 0) {
>> +      CONST UINT64 *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
>
> not sure if this TODO is up-to-date
>

A legal device tree blob could potentially use 4 byte quantities on 32
bit, so I intend to fix this for v4 as well.

>> +      //
>> +      RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);
>> +      if (RegProp != 0 && Len == (2 * sizeof (UINT64))) {
>> +
>> +        NewBase = fdt64_to_cpu (RegProp[0]);
>> +        NewSize = fdt64_to_cpu (RegProp[1]);
>> +
>> +        PcdSet64 (PcdSystemMemoryBase, NewBase);
>> +        PcdSet64 (PcdSystemMemorySize, NewSize);
>
> If I recall correctly, you had the idea that PcdSystemMemoryBase should
> not change (ie. we should assert that), and I think I agreed... Hm...
>
> Yes, it's in here:
> <http://thread.gmane.org/gmane.comp.bios.tianocore.devel/8969/focus=9039>.
> Search for "NewBase to be different from 0x4000_0000".
>
> So please add that assert as well. (And, just to be fully safe, you
> might consider turning PcdSystemMemoryBase into fixed-at-build again!)
>

ok

>> +
>> +        DEBUG ((EFI_D_INFO, "KVM: System RAM @ 0x%lx - 0x%lx\n",
>> +           NewBase, NewBase + NewSize - 1));
>> +      } else {
>> +        DEBUG ((EFI_D_ERROR, "KVM: Failed to parse FDT memory node\n"));
>> +      }
>> +      break;
>> +    }
>> +  }
>> +  //
>> +  // We need to make sure that the machine we are running on has at least
>> +  // 128 MB of memory configured, and does not run from shadowed NOR. This
>
> suggesting wording cleanup: "and is currently executing this binary from
> NOR flash".
>
>> +  // prevents the device tree at base of DRAM from getting clobbered before we
>
> "... from getting clobbered [when our caller installs permanent PEI
> RAM,] before ..."
>
>> +  // have a chance of marking its location as reserved or moving it out of the
>> +  // way.
>
> ... copy it to a freshly allocated block in the permanent PEI RAM in the
> platform PEIM...
>
> I think we can be specific.
>

^C^V

>> +  //
>> +  ASSERT (NewSize >= SIZE_128MB);
>> +  ASSERT ((UINT64)PcdGet32 (PcdFdBaseAddress) + (UINT64)PcdGet32 (PcdFdSize) <= NewBase
>> +          || (UINT64)PcdGet32 (PcdFdBaseAddress) >= NewBase + NewSize);
>> +}
>
> Operator || should go to the end of the first line.
>
> Also, edk2's line wrapping style prescribes one or two spaces
> indentation, relative to the function's or macro's *name*, whose
> argument list you are wrapping. Like this:
>
>   ASSERT (
>     ((UINT64)PcdGet32 (PcdFdBaseAddress) +
>      (UINT64)PcdGet32 (PcdFdSize)) <= NewBase ||
>     (UINT64)PcdGet32 (PcdFdBaseAddress) >= NewBase + NewSize);
>
> Otherwise, this matches our discussion in the same message (linked
> above), thanks!
>

>> +
>> +VOID
>> +ArmPlatformGetPlatformPpiList (
>> +  OUT UINTN                   *PpiListSize,
>> +  OUT EFI_PEI_PPI_DESCRIPTOR  **PpiList
>> +  )
>> +{
>> +  *PpiListSize = 0;
>> +  *PpiList = NULL;
>> +}
>
> I guess this is fine.
>
>> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMHelper.S b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMHelper.S
>> new file mode 100644
>> index 000000000000..af028038b4a6
>> --- /dev/null
>> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMHelper.S
>> @@ -0,0 +1,86 @@
>> +#
>> +#  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_EXPORT(ArmGetPhysAddrTop)
>> +
>> +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
>> +
>> +//EFI_PHYSICAL_ADDRESS
>> +//GetPhysAddrTop (
>> +//  VOID
>> +//  );
>> +ASM_PFX(ArmGetPhysAddrTop):
>> +  mrs   x0, id_aa64mmfr0_el1
>> +  adr   x1, .LPARanges
>> +  and   x0, x0, #7
>> +  ldrb  w1, [x1, x0]
>> +  mov   x0, #1
>> +  lsl   x0, x0, x1
>> +  ret
>> +.LPARanges:
>> +  .byte 32, 36, 40, 42, 44, 48, -1, -1
>> +
>> +ASM_FUNCTION_REMOVE_IF_UNREFERENCED
>
> This I can't validate...
>
>> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMMem.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMMem.c
>> new file mode 100644
>> index 000000000000..f1ea66468027
>> --- /dev/null
>> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMMem.c
>> @@ -0,0 +1,102 @@
>> +/** @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
>> +
>> +EFI_PHYSICAL_ADDRESS
>> +ArmGetPhysAddrTop (
>> +  VOID
>> +  );
>> +
>> +/**
>> +  Return the Virtual Memory Map of your platform
>> +
>> +  This Virtual Memory Map is used by MemoryInitPei Module to initialize the MMU
>> +  on your platform.
>> +
>> +  @param[out]   VirtualMemoryMap    Array of ARM_MEMORY_REGION_DESCRIPTOR
>> +                                    describing a Physical-to-Virtual Memory
>> +                                    mapping. This array must be ended by a
>> +                                    zero-filled entry
>> +
>> +**/
>> +VOID
>> +ArmPlatformGetVirtualMemoryMap (
>> +  IN ARM_MEMORY_REGION_DESCRIPTOR** VirtualMemoryMap
>> +  )
>> +{
>> +  ARM_MEMORY_REGION_ATTRIBUTES  CacheAttributes;
>> +  ARM_MEMORY_REGION_DESCRIPTOR  *VirtualMemoryTable;
>> +
>> +  ASSERT (VirtualMemoryMap != NULL);
>> +
>> +  VirtualMemoryTable = AllocatePages (EFI_SIZE_TO_PAGES (
>> +                                     sizeof (ARM_MEMORY_REGION_DESCRIPTOR)
>> +                                     * MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS));
>
> The utterly pedantic formatting would be
>
> VirtualMemoryTable = AllocatePages (
>                        EFI_SIZE_TO_PAGES (
>                          sizeof (ARM_MEMORY_REGION_DESCRIPTOR) *
>                          MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS)
>                          )
>                        );
>
> I leave it to you...
>

No no, I am going for full marks!

>> +  if (VirtualMemoryTable == NULL) {
>> +    DEBUG ((EFI_D_ERROR, "%a: Error: Failed AllocatePages()\n", __FUNCTION__));
>> +    return;
>> +  }
>> +
>> +  if (FeaturePcdGet (PcdCacheEnable) == TRUE) {
>> +      CacheAttributes = DDR_ATTRIBUTES_CACHED;
>> +  } else {
>> +      CacheAttributes = DDR_ATTRIBUTES_UNCACHED;
>> +  }
>
> Okay, we set this PCD to TRUE in the DSC.
>
>> +
>> +  // 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_INFO, "%a: Dumping System DRAM Memory Map:\n"
>> +      "\tPhysicalBase: 0x%lX\n"
>> +      "\tVirtualBase: 0x%lX\n"
>> +      "\tLength: 0x%lX\n",
>> +      __FUNCTION__,
>> +      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       = ArmGetPhysAddrTop () - VirtualMemoryTable[2].PhysicalBase;
>> +  VirtualMemoryTable[2].Attributes   = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
>> +
>
> Seems reasonable.
>
>> +  // End of Table
>> +  VirtualMemoryTable[3] = (ARM_MEMORY_REGION_DESCRIPTOR){};
>
> Yikes! Edk2 coding style violation galore! :)
> - Structure assignment!
> - Compound literal!!
> - GNUism in initializer list: {} -- meaning in fact { 0 }!!!
>
> Please replace this with a simple ZeroMem() call.
>

ok
Ard Biesheuvel Aug. 28, 2014, 1:11 p.m. UTC | #13
On 28 August 2014 14:50, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> On 28 August 2014 14:03, Laszlo Ersek <lersek@redhat.com> wrote:
>> comments below
>>
>> On 08/27/14 17:12, Ard Biesheuvel wrote:
>>
>>> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/AArch64KVMLib.inf b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/AArch64KVMLib.inf
>>> new file mode 100644
>>> index 000000000000..b30d70f3a1ed
>>> --- /dev/null
>>> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/AArch64KVMLib.inf
>>> @@ -0,0 +1,57 @@
>>> +#/* @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
>>
>> BASE_NAME and containing directory name should be cleaned up, plus
>> perhaps Aarch64 reference should be generalized
>>
>
> OK, already part of my big refactor
>
>>> +  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
>>> +  gArmPlatformTokenSpaceGuid.PcdSystemMemoryInitializeInSec
>>> +
>>> +[Pcd]
>>> +  gArmTokenSpaceGuid.PcdSystemMemoryBase
>>> +  gArmTokenSpaceGuid.PcdSystemMemorySize
>>> +  gArmTokenSpaceGuid.PcdDeviceTreeBaseAddress
>>> +
>>> +[FixedPcd]
>>> +  gArmTokenSpaceGuid.PcdArmPrimaryCoreMask
>>> +  gArmTokenSpaceGuid.PcdArmPrimaryCore
>>> +
>>> +  gArmPlatformTokenSpaceGuid.PcdCoreCount
>>> +  gArmTokenSpaceGuid.PcdFdBaseAddress
>>> +  gArmTokenSpaceGuid.PcdFdSize
>>
>>> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVM.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVM.c
>>> new file mode 100644
>>> index 000000000000..cd9edfe5138b
>>> --- /dev/null
>>> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVM.c
>>> @@ -0,0 +1,143 @@
>>> +/** @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;
>>> +}
>>
>> Yes, this seems sane.
>>
>>> +
>>> +/**
>>> +  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
>>> +  )
>>> +{
>>> +  //
>>> +  // We are relying on ArmPlatformInitializeSystemMemory () being called from
>>> +  // InitializeMemory (), which only occurs if the following feature is disabled
>>> +  //
>>> +  ASSERT (!FeaturePcdGet (PcdSystemMemoryInitializeInSec));
>>> +  return RETURN_SUCCESS;
>>> +}
>>
>> Great; we agreed upon this in
>> <http://thread.gmane.org/gmane.comp.bios.tianocore.devel/8969/focus=9040>.
>> Thanks.
>>
>>> +
>>> +/**
>>> +  Initialize the system (or sometimes called permanent) memory
>>> +
>>> +  This memory is generally represented by the DRAM.
>>> +
>>> +**/
>>> +VOID
>>> +ArmPlatformInitializeSystemMemory (
>>> +  VOID
>>> +  )
>>> +{
>>> +  VOID   *DeviceTreeBase;
>>> +  INT32   Node, Prev;
>>> +  UINT64  NewBase = 0;
>>> +  UINT64  NewSize = 0;
>>
>> Initialization of auto variables is frowned upon in edk2; please use
>> separate assignments.
>>
>
> OK
>
>>> +
>>> +  DeviceTreeBase = (VOID *)PcdGet64 (PcdDeviceTreeBaseAddress);
>>
>> I suggest an intervening (UINTN) cast here, otherwise you might get
>> warnings in a 32-bit build.
>>
>>> +  ASSERT (DeviceTreeBase != NULL);
>>
>> In the hope that I'm not suggesting something insane, you might also
>> want to assert at this point that PcdDeviceTreeBaseAddress equals
>> PcdSystemMemoryBase.
>>
>
> I don't think it is necessary for this module to be that rigid.
> In particular, now that we have PcdDeviceTreeBaseAddress, we can
> define it in the DSC, and in QEMU's case, its default value will be
> 0x4000_0000.
> Then, if you are using a slightly different flavor of emulation, it
> would be perfectly legal to define this to point elsewhere (as long as
> it points to where you are in fact putting the DTB). If this address
> is not covered by system DRAM, that is perfectly fine. In fact, the
> asserts should only fire if we detect here that
> PcdDeviceTreeBaseAddress is in DRAM, and PlatformPeim() should only
> perform the relocation under that condition as well.
>

Actually, for the latter it doesn't make a lot of sense to do that, as
you would just use the plain one in that case.

I am in two minds about this: on the one hand, I don't want to
introduce rigidity that we need to remove again once we start reusing
these modules for Xen, for instance.
On the other hand, I don't think there is any other location of which
we can guarantee that it will remain untouched.

>>> +
>>> +  //
>>> +  // Make sure we have a valid device tree blob at the base of DRAM
>>> +  //
>>> +  if (fdt_check_header (DeviceTreeBase) != 0)
>>> +    return;
>>
>> I believe this should be asserted instead. If this fails, we're doomed.
>>
>
> Agreed.
>
>>> +
>>> +  //
>>> +  // Look for a memory node
>>> +  // TODO handle disjoint memory
>>> +  //
>>
>> Please drop the TODO; I don't think we want to handle disjoint memory
>> very soon, and even then it would take more intrusive changes than what
>> is marked here, locally, with this comment.
>>
>
> ok
>
>>> +  for (Prev = 0;; Prev = Node) {
>>> +    CONST CHAR8  *Type;
>>> +    INT32         Len;
>>> +
>>> +    Node = fdt_next_node (DeviceTreeBase, Prev, NULL);
>>> +    if (Node < 0)
>>> +      return;
>>
>> Braces. Also, I think we should rather break here, not return; the
>> ASSERT()s after the loop should run in either case. If we don't find any
>> good node, then the ASSERTs() should trigger.
>>
>>> +
>>> +    Type = fdt_getprop (DeviceTreeBase, Node, "device_type", &Len);
>>> +    if (Type && AsciiStrnCmp (Type, "memory", Len) == 0) {
>>> +      CONST UINT64 *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
>>
>> not sure if this TODO is up-to-date
>>
>
> A legal device tree blob could potentially use 4 byte quantities on 32
> bit, so I intend to fix this for v4 as well.
>
>>> +      //
>>> +      RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);
>>> +      if (RegProp != 0 && Len == (2 * sizeof (UINT64))) {
>>> +
>>> +        NewBase = fdt64_to_cpu (RegProp[0]);
>>> +        NewSize = fdt64_to_cpu (RegProp[1]);
>>> +
>>> +        PcdSet64 (PcdSystemMemoryBase, NewBase);
>>> +        PcdSet64 (PcdSystemMemorySize, NewSize);
>>
>> If I recall correctly, you had the idea that PcdSystemMemoryBase should
>> not change (ie. we should assert that), and I think I agreed... Hm...
>>
>> Yes, it's in here:
>> <http://thread.gmane.org/gmane.comp.bios.tianocore.devel/8969/focus=9039>.
>> Search for "NewBase to be different from 0x4000_0000".
>>
>> So please add that assert as well. (And, just to be fully safe, you
>> might consider turning PcdSystemMemoryBase into fixed-at-build again!)
>>
>
> ok
>
>>> +
>>> +        DEBUG ((EFI_D_INFO, "KVM: System RAM @ 0x%lx - 0x%lx\n",
>>> +           NewBase, NewBase + NewSize - 1));
>>> +      } else {
>>> +        DEBUG ((EFI_D_ERROR, "KVM: Failed to parse FDT memory node\n"));
>>> +      }
>>> +      break;
>>> +    }
>>> +  }
>>> +  //
>>> +  // We need to make sure that the machine we are running on has at least
>>> +  // 128 MB of memory configured, and does not run from shadowed NOR. This
>>
>> suggesting wording cleanup: "and is currently executing this binary from
>> NOR flash".
>>
>>> +  // prevents the device tree at base of DRAM from getting clobbered before we
>>
>> "... from getting clobbered [when our caller installs permanent PEI
>> RAM,] before ..."
>>
>>> +  // have a chance of marking its location as reserved or moving it out of the
>>> +  // way.
>>
>> ... copy it to a freshly allocated block in the permanent PEI RAM in the
>> platform PEIM...
>>
>> I think we can be specific.
>>
>
> ^C^V
>
>>> +  //
>>> +  ASSERT (NewSize >= SIZE_128MB);
>>> +  ASSERT ((UINT64)PcdGet32 (PcdFdBaseAddress) + (UINT64)PcdGet32 (PcdFdSize) <= NewBase
>>> +          || (UINT64)PcdGet32 (PcdFdBaseAddress) >= NewBase + NewSize);
>>> +}
>>
>> Operator || should go to the end of the first line.
>>
>> Also, edk2's line wrapping style prescribes one or two spaces
>> indentation, relative to the function's or macro's *name*, whose
>> argument list you are wrapping. Like this:
>>
>>   ASSERT (
>>     ((UINT64)PcdGet32 (PcdFdBaseAddress) +
>>      (UINT64)PcdGet32 (PcdFdSize)) <= NewBase ||
>>     (UINT64)PcdGet32 (PcdFdBaseAddress) >= NewBase + NewSize);
>>
>> Otherwise, this matches our discussion in the same message (linked
>> above), thanks!
>>
>
>>> +
>>> +VOID
>>> +ArmPlatformGetPlatformPpiList (
>>> +  OUT UINTN                   *PpiListSize,
>>> +  OUT EFI_PEI_PPI_DESCRIPTOR  **PpiList
>>> +  )
>>> +{
>>> +  *PpiListSize = 0;
>>> +  *PpiList = NULL;
>>> +}
>>
>> I guess this is fine.
>>
>>> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMHelper.S b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMHelper.S
>>> new file mode 100644
>>> index 000000000000..af028038b4a6
>>> --- /dev/null
>>> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMHelper.S
>>> @@ -0,0 +1,86 @@
>>> +#
>>> +#  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_EXPORT(ArmGetPhysAddrTop)
>>> +
>>> +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
>>> +
>>> +//EFI_PHYSICAL_ADDRESS
>>> +//GetPhysAddrTop (
>>> +//  VOID
>>> +//  );
>>> +ASM_PFX(ArmGetPhysAddrTop):
>>> +  mrs   x0, id_aa64mmfr0_el1
>>> +  adr   x1, .LPARanges
>>> +  and   x0, x0, #7
>>> +  ldrb  w1, [x1, x0]
>>> +  mov   x0, #1
>>> +  lsl   x0, x0, x1
>>> +  ret
>>> +.LPARanges:
>>> +  .byte 32, 36, 40, 42, 44, 48, -1, -1
>>> +
>>> +ASM_FUNCTION_REMOVE_IF_UNREFERENCED
>>
>> This I can't validate...
>>
>>> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMMem.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMMem.c
>>> new file mode 100644
>>> index 000000000000..f1ea66468027
>>> --- /dev/null
>>> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMMem.c
>>> @@ -0,0 +1,102 @@
>>> +/** @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
>>> +
>>> +EFI_PHYSICAL_ADDRESS
>>> +ArmGetPhysAddrTop (
>>> +  VOID
>>> +  );
>>> +
>>> +/**
>>> +  Return the Virtual Memory Map of your platform
>>> +
>>> +  This Virtual Memory Map is used by MemoryInitPei Module to initialize the MMU
>>> +  on your platform.
>>> +
>>> +  @param[out]   VirtualMemoryMap    Array of ARM_MEMORY_REGION_DESCRIPTOR
>>> +                                    describing a Physical-to-Virtual Memory
>>> +                                    mapping. This array must be ended by a
>>> +                                    zero-filled entry
>>> +
>>> +**/
>>> +VOID
>>> +ArmPlatformGetVirtualMemoryMap (
>>> +  IN ARM_MEMORY_REGION_DESCRIPTOR** VirtualMemoryMap
>>> +  )
>>> +{
>>> +  ARM_MEMORY_REGION_ATTRIBUTES  CacheAttributes;
>>> +  ARM_MEMORY_REGION_DESCRIPTOR  *VirtualMemoryTable;
>>> +
>>> +  ASSERT (VirtualMemoryMap != NULL);
>>> +
>>> +  VirtualMemoryTable = AllocatePages (EFI_SIZE_TO_PAGES (
>>> +                                     sizeof (ARM_MEMORY_REGION_DESCRIPTOR)
>>> +                                     * MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS));
>>
>> The utterly pedantic formatting would be
>>
>> VirtualMemoryTable = AllocatePages (
>>                        EFI_SIZE_TO_PAGES (
>>                          sizeof (ARM_MEMORY_REGION_DESCRIPTOR) *
>>                          MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS)
>>                          )
>>                        );
>>
>> I leave it to you...
>>
>
> No no, I am going for full marks!
>
>>> +  if (VirtualMemoryTable == NULL) {
>>> +    DEBUG ((EFI_D_ERROR, "%a: Error: Failed AllocatePages()\n", __FUNCTION__));
>>> +    return;
>>> +  }
>>> +
>>> +  if (FeaturePcdGet (PcdCacheEnable) == TRUE) {
>>> +      CacheAttributes = DDR_ATTRIBUTES_CACHED;
>>> +  } else {
>>> +      CacheAttributes = DDR_ATTRIBUTES_UNCACHED;
>>> +  }
>>
>> Okay, we set this PCD to TRUE in the DSC.
>>
>>> +
>>> +  // 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_INFO, "%a: Dumping System DRAM Memory Map:\n"
>>> +      "\tPhysicalBase: 0x%lX\n"
>>> +      "\tVirtualBase: 0x%lX\n"
>>> +      "\tLength: 0x%lX\n",
>>> +      __FUNCTION__,
>>> +      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       = ArmGetPhysAddrTop () - VirtualMemoryTable[2].PhysicalBase;
>>> +  VirtualMemoryTable[2].Attributes   = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
>>> +
>>
>> Seems reasonable.
>>
>>> +  // End of Table
>>> +  VirtualMemoryTable[3] = (ARM_MEMORY_REGION_DESCRIPTOR){};
>>
>> Yikes! Edk2 coding style violation galore! :)
>> - Structure assignment!
>> - Compound literal!!
>> - GNUism in initializer list: {} -- meaning in fact { 0 }!!!
>>
>> Please replace this with a simple ZeroMem() call.
>>
>
> ok
>
> --
> Ard.

------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Laszlo Ersek Aug. 28, 2014, 1:51 p.m. UTC | #14
On 08/28/14 14:50, Ard Biesheuvel wrote:
> On 28 August 2014 14:03, Laszlo Ersek <lersek@redhat.com> wrote:
>> comments below
>>
>> On 08/27/14 17:12, Ard Biesheuvel wrote:
>>

>>> +  ASSERT (DeviceTreeBase != NULL);
>>
>> In the hope that I'm not suggesting something insane, you might also
>> want to assert at this point that PcdDeviceTreeBaseAddress equals
>> PcdSystemMemoryBase.
>>
> 
> I don't think it is necessary for this module to be that rigid.
> In particular, now that we have PcdDeviceTreeBaseAddress, we can
> define it in the DSC, and in QEMU's case, its default value will be
> 0x4000_0000.
> Then, if you are using a slightly different flavor of emulation, it
> would be perfectly legal to define this to point elsewhere (as long as
> it points to where you are in fact putting the DTB). If this address
> is not covered by system DRAM, that is perfectly fine.

Agreed.

> In fact, the
> asserts should only fire if we detect here that
> PcdDeviceTreeBaseAddress is in DRAM, and PlatformPeim() should only
> perform the relocation under that condition as well.

I agree.

But, this is quickly getting quite hairy, so, for now, can you please
just ignore my above ASSERT() suggestion, and keep the rest of the
ASSERT()s as we discussed before? It's already quite hard to keep track
all of this. If you made them more dynamic only later, in further
patches, that would keep my present review manageable (as opposed to,
well, mind-boggling :))

>>> +  VirtualMemoryTable = AllocatePages (EFI_SIZE_TO_PAGES (
>>> +                                     sizeof (ARM_MEMORY_REGION_DESCRIPTOR)
>>> +                                     * MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS));
>>
>> The utterly pedantic formatting would be
>>
>> VirtualMemoryTable = AllocatePages (
>>                        EFI_SIZE_TO_PAGES (
>>                          sizeof (ARM_MEMORY_REGION_DESCRIPTOR) *
>>                          MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS)
>>                          )
>>                        );
>>
>> I leave it to you...
>>
> 
> No no, I am going for full marks!

Haha, great; thanks :)
Laszlo


------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Laszlo Ersek Aug. 28, 2014, 2:03 p.m. UTC | #15
On 08/28/14 15:11, Ard Biesheuvel wrote:
> On 28 August 2014 14:50, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:

>> I don't think it is necessary for this module to be that rigid.
>> In particular, now that we have PcdDeviceTreeBaseAddress, we can
>> define it in the DSC, and in QEMU's case, its default value will be
>> 0x4000_0000.
>> Then, if you are using a slightly different flavor of emulation, it
>> would be perfectly legal to define this to point elsewhere (as long as
>> it points to where you are in fact putting the DTB). If this address
>> is not covered by system DRAM, that is perfectly fine. In fact, the
>> asserts should only fire if we detect here that
>> PcdDeviceTreeBaseAddress is in DRAM, and PlatformPeim() should only
>> perform the relocation under that condition as well.
>>
> 
> Actually, for the latter it doesn't make a lot of sense to do that, as
> you would just use the plain one in that case.
> 
> I am in two minds about this: on the one hand, I don't want to
> introduce rigidity that we need to remove again once we start reusing
> these modules for Xen, for instance.
> On the other hand, I don't think there is any other location of which
> we can guarantee that it will remain untouched.

Predictably, I agree with the "on the other hand" statement.

Remember that we discussed options that would have
- moved up the DTB from 1G to 1G+16M, or
- moved it out of DRAM completely (to sth like fw_cfg, MMIO).

We discussed the 1G+16M option for reasons that are no longer relevant
(we were still considering an in-place memalloc HOB, while not bothering
the guest kernel with it). But still, placing the DTB anywhere else than
the bottom of system RAM might require more intrusive changes to
InitializeMemory(), which is (thus far) shared by all ARM platforms.

We already need quite elaborate ASSERT()s in our
ArmPlatformInitializeSystemMemory() version, so that InitializeMemory()
is forced to the Right Path (TM).

The other option, ie. moving the DTB from DRAM to MMIO would have been
the easiest for edk2 all along, but it's new hardware for QEMU, and
Peter doesn't like that.

So, let's just stick with the bottom of the system DRAM for now. And
I'll trust you to heed or ignore my request for an explicit assert :)

Thanks,
Laszlo

------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Laszlo Ersek Aug. 28, 2014, 2:30 p.m. UTC | #16
comments below

On 08/27/14 17:12, Ard Biesheuvel wrote:

> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization-KVM.dsc b/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization-KVM.dsc
> new file mode 100644
> index 000000000000..89c5ff134b41
> --- /dev/null
> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization-KVM.dsc
> @@ -0,0 +1,222 @@
> +#
> +#  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

Good, this should be resolved with our own library instance. OK.

> +
> +  # Virtio Support
> +  VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
> +  VirtioMmioDeviceLib|OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf
> +
> +  ArmPlatformSysConfigLib|ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationSysConfigLibKVM/AArch64VirtualizationSysConfigLibKVM.inf

Yes, use our own. OK.

> +
> +  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

This is the hack whereby we end up needing / using "ArmPlatform.h". If
that's the tradition in ArmPlatformPkg, I'm OK with it.

> +
> +
> +################################################################################
> +#
> +# 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|0x80000040

This PCD is important (for debugging). I propose 0x8000004F:

  # DEBUG_ERROR    0x80000000 Error
  # DEBUG_INFO     0x00000040 Informational debug messages
  # DEBUG_FS       0x00000008 EFI File system
  # DEBUG_LOAD     0x00000004 Load events
  # DEBUG_WARN     0x00000002 Warnings
  # DEBUG_INIT     0x00000001 Initialization

In addition, PcdDebugPrintErrorLevel is also set in the include file (to
0x8000000F), but since this setting comes after the !include directive,
this one takes effect. I think having two settings is confusing, so
please keep only one.

> +
> +  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
> +

Whatever I understand from these seem reasonable (we discussed some of
them before).

> +  #
> +  # 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
> +  #
> +  gArmPlatformTokenSpaceGuid.PcdDefaultBootDescription|L"Linux (EFI stub) on virtio31:hd0:part0"
> +  gArmPlatformTokenSpaceGuid.PcdDefaultBootDevicePath|L"VenHw(837DCA9E-E874-4D82-B29A-23FE0E23D1E2,003E000A00000000)/HD(1,MBR,0x00000000,0x3F,0x19FC0)/Image"
> +  gArmPlatformTokenSpaceGuid.PcdDefaultBootArgument|"root=/dev/vda2 console=ttyAMA0,38400n8 earlycon=pl011,0x9000000 uefi_debug"
> +  gArmPlatformTokenSpaceGuid.PcdDefaultBootType|0

It's impossible to set a "robust" value here, but the VenHw node at
least should reflect the "new" format, ie. where we include the UINT64
register block base address rather than the UINT32 instance number.

> +
> +   # 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)/VenVt100()"
> +  gArmPlatformTokenSpaceGuid.PcdDefaultConInPaths|L"VenHw(D3987D4B-971A-435F-8CAF-4967EB627241)/Uart(38400,8,N,1)/VenVt100()"
> +  gArmPlatformTokenSpaceGuid.PcdPlatformBootTimeOut|3

Okay, looks like we managed to request VT100 terminals after all! :)

> +
> +  #
> +  # 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

Right. As mentioned recently, I think we actually want to keep
PcdSystemMemoryBase fixed-at-build.

> +
> +  # location of the device tree blob passed by QEMU
> +  gArmTokenSpaceGuid.PcdDeviceTreeBaseAddress|0x40000000
> +
> +  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

Huh, I wonder if we need this! We have very similar code in
"ArmPlatformPkg/PlatformPei/PlatformPeim.c".

I do see that many ARM platforms include
"Nt32Pkg/BootModePei/BootModePei.inf". I think they all should drop it.

Well, actually, this Nt32 PEIM is *not* included in the FDF file. Which
is correct. However, we shouldn't even build it -- remove it from the
DSC, please.

> +  MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
> +  MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf {
> +    <LibraryClasses>
> +      NULL|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
> +  }

Okay, I had a small heart attack here, but I'm recovering now :)

I didn't understand for a moment why we needed this decompression thing.
I was confused by my OVMF background: in OVMF, the *SEC* phase
decompresses "stuff" that ends up carrying both PEIMs and DXE modules.

Clearly this would be fatal for us here, because such decompression
would need *some* system DRAM initialization *in SEC*, and in
particular, writes to DRAM. And

(a) that's the very PCD that we assert to be FALSE,

(b) the code in InitializeMemory() and our
    ArmPlatformInitializeSystemMemory() version works with the FD (not
    any potentially decompressed FV!) boundaries.

Then I noticed that this library was plugged into DxeIpl (DXE Initial
Program Load) only. That's a completely different matter, and we're
safe. In the aarch64 guest, the PEI phase will execute binaries (PEIMs)
from NOR flash. Okay. Phew.

Another strong hint is that the library class "ExtractGuidedSectionLib"
(for which LzmaCustomDecompressLib is a "plugin") is *only* ever
resolved to these two instances:
- PeiExtractGuidedSectionLib
- DxeExtractGuidedSectionLib

None of these are usable in SEC; you can see the client module type
restrictions in the LIBRARY_CLASS defines of their INF files.

(See also git commit ad43bc6b for some background.)

So, all's fine; I'll return to this in the FDF review, below.

> +
> +  #
> +  # 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

Yay! :)

... Actually, VirtioPciDeviceDxe should be dropped.

We don't have PCI emulation yet. Even if we had it in QEMU (I got no
idea), then we don't have a root bridge driver for it in edk2. So
nothing will enumerate PCI devices, nothing will create PciIo protocol
instances.

Hence the VirtioPciDeviceDxe driver (a UEFI driver compliant with the
UEFI driver model) will never install a VirtioProtocol instance on any
handle that has a PciIo protocol instance. Simply by virtue of such a
handle not existing.

This is why we have DTB-based virtio-mmio enumeration in the platform
driver, and why we use VirtioMmioDeviceLib.

So, please drop VirtioPciDeviceDxe; we can easily add it later, if it'll
ever make sense in aarch64 guests (and someone writes an edk2 root
bridge driver for it).

> +
> +
> +  #
> +  # 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..78efb8dbb100
> --- /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

Two megs, okay.

> +
> +# This one is tricky, it must be: BlockSize * NumBlocks = Size
> +BlockSize     = 0x00001000
> +NumBlocks     = 0x200
> +

Yes, 4K is usual.

> +################################################################################
> +#
> +# 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.

You could say "the C language doesn't favor dereferencing of NULL
pointers" as well :)

> +# So instead, put 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

Awesome, thanks.

And, these are the FV PCDs that we reference in
"ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformPeiLib.c",
function PlatformPeim():

  BuildFvHob (PcdGet32(PcdFvBaseAddress), PcdGet32(PcdFvSize));

This will tell DXE where to look for a firmware volume. And, in DXE, we
*can* decompress things! Okay.

BTW, the offsets here are listed relative to the start of the FD, but
the PCDs take absolute values. Currently that means the same thing
because the FD's BaseAddress is zero.

For clarity, I'll now quote the rest of this patch out of order.

> +
> +
> +################################################################################
> +#
> +# 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_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
> +    }
> +  }
> +
> +

So we got, in the NOR-mapped FD file:

address 0:  jump instruction to 4K, otherwise a bunch of emptiness
            (according to erase polarity!)

address 4K: a firmware volume (FVMAIN_COMPACT) with an FFS (firmware
            volume file system) that contains the following files:

            - a bunch of *uncompressed* PEIMs

            - a special file called APRIORI file, prescribing dispatch
              order for the PEI dispatcher. People always put the PCD
              PEIM first, as I recall. That's because it needs to set up
              the PCD database, copying the in-flash PCD DB (an
              implicitly built FFS file) into memory (a special HOB in
              temporary RAM), and it allows all other PEIMs to use PCDs.

            - an FFS file that has a section:

              - which is *compressed*, and has GUID EE4E5898...,
                corresponding to gLzmaCustomDecompressGuid -- this will
                connect the section to LzmaCustomDecompressLib above!

              - and which section embeds another firmware volume, called
                FVMAIN (see just below), with an FFS that contains the
                following files:

                - a bunch of DXE modules,

                - a special file called APRIORI file, prescribing
                  dispatch order for the DXE dispatcher. The PCD driver
                  comes first, again.

This is very nice. SEC and PEI modules are uncompressed in the FD, they
run from NOR flash. The DXE IPL (DXE initial program load) PEIM, the
last PEIM that runs in PEI, will decompress FVMAIN from the compressed
FFS file section, from NOR flash to RAM, will scan the new firmware
volume (in RAM), and then DXE modules, including the DXE_CORE, will run
from RAM. By that time, our DTB will have been relocated and protected.
Cool.

> +[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

Again, pls. drop VirtioPciDeviceDxe.

> +
> +  #
> +  # UEFI application (Shell Embedded Boot Loader)
> +  #
> +  INF ShellBinPkg/UefiShell/UefiShell.inf

It would be nice *not* to use the prebuilt UEFI shell binary. Instead,
we could build the UEFI shell from source. Please search OvmfPkgX64.dsc
and OvmfPkgX64.fdf for "ShellPkg/Application/Shell/Shell.inf", and
consider stealing what you can.

This allows you to do UEFI shell development flexibly -- your develop /
build / reboot / test cycle can now cover the UEFI shell as well. It
also enables you to take advantage of ShellPkg commits as soon as they
appear in the tree, no need to wait for periodic binary syncs in
ShellBinPkg.

> +
> +  #
> +  # Bds
> +  #
> +  INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
> +  INF ArmPlatformPkg/Bds/Bds.inf
> +
> +

I'll just assume that the following rules have been copied verbatim from
existent platforms:

> +################################################################################
> +#
> +# 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
> +  }
> +

Okay. Now back to the DSC inc file:

> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization.dsc.inc b/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization.dsc.inc
> new file mode 100644
> index 000000000000..67c024feb086
> --- /dev/null
> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization.dsc.inc
> @@ -0,0 +1,336 @@
> +#
> +#  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
> +
> +  PlatformPeiLib|ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformPeiLib.inf
> +  EfiResetSystemLib|ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.inf

Correct, both of these.

We've now put to use all four library instances that we introduce, good.

> +
> +  # 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
> +

This part is probably not absolutely minimal, but if it works, it's
good.

> +################################################################################
> +#
> +# 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
> +
> +[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

Ditto.

Also, I'd prefer if each PCD was mentioned only once, across the DSC and
the DSC.inc cumulatively, but this is really the lowest priority
imaginable.

I'm glad I ultimately forced myself to review these files. I now
understand the flash layout, thanks to the FDF, and it's reassuring that
it matches the assumptions that I've been operating under (and that you
tested), wrt. the PEIMs we care about strongly executing from NOR flash,
decompression of FVs, etc.

I feel great about this work. Looking forward to version 4. :)

Thanks,
Laszlo

------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Peter Maydell Aug. 28, 2014, 2:52 p.m. UTC | #17
On 28 August 2014 15:30, Laszlo Ersek <lersek@redhat.com> wrote:
> So we got, in the NOR-mapped FD file:
>
> address 0:  jump instruction to 4K, otherwise a bunch of emptiness
>             (according to erase polarity!)

Ideally this should be a proper complete vector table with
handlers for all the exception vectors. In particular it is a
nice touch if exceptions for things like invalid accesses
and undefined instructions end up in some sort of panic-abort
function that dumps a diagnostic message to the UART.
This isn't necessary for proper operation but it's handy if
you're trying to debug either UEFI itself or early kernel startup.
As a minimum you want to have them go somewhere sensible
(like a jump-to-self instruction) so that we definitely don't just
try to reenter UEFI at its start point (an effect that is more
likely in 32-bit ARM where the all-zeroes instruction is a NOP).

Does UEFI install a proper vector table at some point in
bootup by writing to the vector base address register? If
not then providing a sensible initial set of vectors is even
more important.

thanks
-- PMM

------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Ard Biesheuvel Aug. 28, 2014, 2:59 p.m. UTC | #18
On 28 August 2014 16:52, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 28 August 2014 15:30, Laszlo Ersek <lersek@redhat.com> wrote:
>> So we got, in the NOR-mapped FD file:
>>
>> address 0:  jump instruction to 4K, otherwise a bunch of emptiness
>>             (according to erase polarity!)
>
> Ideally this should be a proper complete vector table with
> handlers for all the exception vectors. In particular it is a
> nice touch if exceptions for things like invalid accesses
> and undefined instructions end up in some sort of panic-abort
> function that dumps a diagnostic message to the UART.
> This isn't necessary for proper operation but it's handy if
> you're trying to debug either UEFI itself or early kernel startup.
> As a minimum you want to have them go somewhere sensible
> (like a jump-to-self instruction) so that we definitely don't just
> try to reenter UEFI at its start point (an effect that is more
> likely in 32-bit ARM where the all-zeroes instruction is a NOP).
>

Fortunately, the NOR images are padded with 0xff, so that is covered.

> Does UEFI install a proper vector table at some point in
> bootup by writing to the vector base address register? If
> not then providing a sensible initial set of vectors is even
> more important.
>

It does install a proper vector table, and contains exception handling
code to at least produce some meaningful output (register dump), at
least on debug builds.

However, putting a vector table in that particular place is
troublesome, as the whole point of having the region is to avoid
putting a Firmware Volume (FV) there. And having to code the whole
vector table in hex inside the DATA = { } is not a great prospect
either.
Laszlo Ersek Aug. 28, 2014, 3:08 p.m. UTC | #19
On 08/28/14 16:52, Peter Maydell wrote:
> On 28 August 2014 15:30, Laszlo Ersek <lersek@redhat.com> wrote:
>> So we got, in the NOR-mapped FD file:
>>
>> address 0:  jump instruction to 4K, otherwise a bunch of emptiness
>>             (according to erase polarity!)
> 
> Ideally this should be a proper complete vector table with
> handlers for all the exception vectors. In particular it is a
> nice touch if exceptions for things like invalid accesses
> and undefined instructions end up in some sort of panic-abort
> function that dumps a diagnostic message to the UART.
> This isn't necessary for proper operation but it's handy if
> you're trying to debug either UEFI itself or early kernel startup.
> As a minimum you want to have them go somewhere sensible
> (like a jump-to-self instruction) so that we definitely don't just
> try to reenter UEFI at its start point (an effect that is more
> likely in 32-bit ARM where the all-zeroes instruction is a NOP).
> 
> Does UEFI install a proper vector table at some point in
> bootup by writing to the vector base address register?

Yes, it does that on x86_64 / OVMF. (The feature comes from UefiCpuPkg.)
The exception type & details (registers etc) are dumped, and even the
offending binary file and RIP are identified in a way that allows one to
correlate the exception with the source code.

However:
- I have no clue if anything similar exists in / for ARM builds.

- Even if someone wants to implement such, where should (where *can*,
  actually) the exception handler table exist at all? The addresses
  that I listed above are backed by the (read-only) flash chip. The
  exception handler table should be built somewhere in DRAM, no?

> If
> not then providing a sensible initial set of vectors is even
> more important.

Hmmm, wait a second, now grepping for CpuExceptionHandlerLib, I'm
actually getting results from ARM packages as well. Ard's series
resolves this library class to:


CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf

Ugh, that's a null library instance; it does nothing. :( If it's any
consolation, "ArmVExpress.dsc.inc" seems to use the same, for the
physical platforms.

... Hm, maybe I'm looking in the wrong place. ARM likely doesn't
actually use CpuExceptionHandlerLib for handling CPU expcetions.

There's this code though:

  ArmPkg/Drivers/CpuDxe/AArch64/Exception.c

I think it covers exactly what you say (or at least participates in it).
People have even submitted patches against it (see git commit 6a343fac
for example.) I'm quite sure the feature you named is covered, but
Olivier should be able to state authoritatively.

Thanks
Laszlo

------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Laszlo Ersek Aug. 28, 2014, 3:16 p.m. UTC | #20
On 08/28/14 16:59, Ard Biesheuvel wrote:
> On 28 August 2014 16:52, Peter Maydell <peter.maydell@linaro.org> wrote:
>> On 28 August 2014 15:30, Laszlo Ersek <lersek@redhat.com> wrote:
>>> So we got, in the NOR-mapped FD file:
>>>
>>> address 0:  jump instruction to 4K, otherwise a bunch of emptiness
>>>             (according to erase polarity!)
>>
>> Ideally this should be a proper complete vector table with
>> handlers for all the exception vectors. In particular it is a
>> nice touch if exceptions for things like invalid accesses
>> and undefined instructions end up in some sort of panic-abort
>> function that dumps a diagnostic message to the UART.
>> This isn't necessary for proper operation but it's handy if
>> you're trying to debug either UEFI itself or early kernel startup.
>> As a minimum you want to have them go somewhere sensible
>> (like a jump-to-self instruction) so that we definitely don't just
>> try to reenter UEFI at its start point (an effect that is more
>> likely in 32-bit ARM where the all-zeroes instruction is a NOP).
>>
> 
> Fortunately, the NOR images are padded with 0xff, so that is covered.

Yes, 0xFF corresponds to ErasePolarity = 1.

> 
>> Does UEFI install a proper vector table at some point in
>> bootup by writing to the vector base address register? If
>> not then providing a sensible initial set of vectors is even
>> more important.
>>
> 
> It does install a proper vector table, and contains exception handling
> code to at least produce some meaningful output (register dump), at
> least on debug builds.

I'm glad that I didn't just post gibberish! :)

> However, putting a vector table in that particular place is
> troublesome, as the whole point of having the region is to avoid
> putting a Firmware Volume (FV) there. And having to code the whole
> vector table in hex inside the DATA = { } is not a great prospect
> either.

I think that the exception vector table simply doesn't *belong* in the
flash.

Thanks,
Laszlo

------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Peter Maydell Aug. 28, 2014, 3:17 p.m. UTC | #21
On 28 August 2014 16:08, Laszlo Ersek <lersek@redhat.com> wrote:
> - Even if someone wants to implement such, where should (where *can*,
>   actually) the exception handler table exist at all? The addresses
>   that I listed above are backed by the (read-only) flash chip. The
>   exception handler table should be built somewhere in DRAM, no?

There's no inherent reason it needs to be in DRAM. For a
boot loader I would expect it to be a minimal assembly
stub that just sets up to call into C code. If you really
need to have runtime dispatch of your exceptions you
can do it by indirection in the C function. If all you're
doing is "blow up and print message to UART" then you
don't need that either, you can just have your panic
handler live in your ROM image.

If you want to get fancier then for AArch64 (and for
AArch32 CPUs with support for the security extensions)
there's a CPU register you can use to put the vector
table somewhere else than the base of RAM. But it's
nice to have a functional vector table out of the gate
to deal with things blowing up before you get round to
installing a table that's somewhere else.

-- PMM

------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Peter Maydell Aug. 28, 2014, 3:17 p.m. UTC | #22
On 28 August 2014 16:16, Laszlo Ersek <lersek@redhat.com> wrote:
> On 08/28/14 16:59, Ard Biesheuvel wrote:
>> However, putting a vector table in that particular place is
>> troublesome, as the whole point of having the region is to avoid
>> putting a Firmware Volume (FV) there. And having to code the whole
>> vector table in hex inside the DATA = { } is not a great prospect
>> either.

This just seems like a flaw in UEFI to me. You really need to
be able to write bits of custom assembly and data to low memory.

> I think that the exception vector table simply doesn't *belong* in the
> flash.

I don't understand that. In the flash seems entirely reasonable
to me...

-- PMM

------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Andrew Fish Aug. 28, 2014, 3:20 p.m. UTC | #23
On Aug 28, 2014, at 8:08 AM, Laszlo Ersek <lersek@redhat.com> wrote:

> On 08/28/14 16:52, Peter Maydell wrote:
>> On 28 August 2014 15:30, Laszlo Ersek <lersek@redhat.com> wrote:
>>> So we got, in the NOR-mapped FD file:
>>> 
>>> address 0:  jump instruction to 4K, otherwise a bunch of emptiness
>>>            (according to erase polarity!)
>> 
>> Ideally this should be a proper complete vector table with
>> handlers for all the exception vectors. In particular it is a
>> nice touch if exceptions for things like invalid accesses
>> and undefined instructions end up in some sort of panic-abort
>> function that dumps a diagnostic message to the UART.
>> This isn't necessary for proper operation but it's handy if
>> you're trying to debug either UEFI itself or early kernel startup.
>> As a minimum you want to have them go somewhere sensible
>> (like a jump-to-self instruction) so that we definitely don't just
>> try to reenter UEFI at its start point (an effect that is more
>> likely in 32-bit ARM where the all-zeroes instruction is a NOP).
>> 
>> Does UEFI install a proper vector table at some point in
>> bootup by writing to the vector base address register?
> 

For x86 protected and long mode there is not a fixed address for the vectors. It is setup via an instruction. 

You can see the code setting up exceptions by searching for the BaseLib function to write lidt.

~/work/src/edk2(master)>git grep AsmWriteIdtr
EdkCompatibilityPkg/Compatibility/BootScriptSaveOnS3SaveStateThunk/X64/DispatchExecute.c:139:  AsmWriteIdtr (Ia32Idtr);
EdkCompatibilityPkg/Compatibility/BootScriptSaveOnS3SaveStateThunk/X64/DispatchExecute.c:153:  AsmWriteIdtr ((IA32_DESCRIPTOR *) &X64Idtr);
EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Include/Library/EdkIIGlueBaseLib.h:6467:AsmWriteIdtr (
EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BaseLib/Ia32/WriteIdtr.asm:18:;   AsmWriteIdtr function
EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BaseLib/Ia32/WriteIdtr.c:2:  AsmWriteIdtr function
EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BaseLib/X64/WriteIdtr.S:18:#   AsmWriteIdtr function
EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BaseLib/X64/WriteIdtr.asm:16:;   AsmWriteIdtr function
EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Library/BaseLib/X86WriteIdtr.c:38:AsmWriteIdtr (
IntelFspPkg/FspSecCore/SecMain.c:101:  AsmWriteIdtr (&IdtDescriptor);
IntelFspPkg/FspSecCore/SecMain.c:192:  AsmWriteIdtr (&IdtDescriptor);
IntelFspWrapperPkg/FspInitPei/SecMain.c:121:  AsmWriteIdtr (&IdtDescriptor);
IntelFspWrapperPkg/FspWrapperSecCore/SecMain.c:116:  AsmWriteIdtr (&IdtDescriptor);
IntelFspWrapperPkg/Library/SecPeiFspPlatformSecLibSample/SecTempRamSupport.c:133:  AsmWriteIdtr (&IdtDescriptor);
MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c:172:    AsmWriteIdtr (&gLidtDescriptor);
MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/IA32/SetIdtEntry.c:39:  AsmWriteIdtr (IdtDescriptor);
MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/SetIdtEntry.c:102:  AsmWriteIdtr (IdtDescriptor);
MdeModulePkg/Universal/CapsulePei/X64/X64Entry.c:56:  AsmWriteIdtr ((IA32_DESCRIPTOR *) &X64Idtr);  
MdeModulePkg/Universal/CapsulePei/X64/X64Entry.c:88:  AsmWriteIdtr ((IA32_DESCRIPTOR *) &Ia32Idtr);  
MdePkg/Include/Library/BaseLib.h:6498:AsmWriteIdtr (
MdePkg/Library/BaseLib/Ia32/WriteIdtr.asm:18:;   AsmWriteIdtr function
MdePkg/Library/BaseLib/Ia32/WriteIdtr.c:2:  AsmWriteIdtr function
MdePkg/Library/BaseLib/X64/WriteIdtr.asm:18:;   AsmWriteIdtr function
MdePkg/Library/BaseLib/X86WriteIdtr.c:2:  IA-32/x64 AsmWriteIdtr()
MdePkg/Library/BaseLib/X86WriteIdtr.c:33:AsmWriteIdtr (
MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointer.c:126:  AsmWriteIdtr (&Idtr);
OvmfPkg/Library/LoadLinuxLib/LinuxGdt.c:179:  AsmWriteIdtr (&IdtPtr);
OvmfPkg/Sec/SecMain.c:726:  AsmWriteIdtr (&IdtDescriptor);
OvmfPkg/Sec/SecMain.c:873:  AsmWriteIdtr (&IdtDescriptor);
SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/DxeDebugAgentLib.c:278:    AsmWriteIdtr ((IA32_DESCRIPTOR *) &Idtr);
SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/DxeDebugAgentLib.c:479:        AsmWriteIdtr (&IdtDescriptor);
SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgent/SmmDebugAgentLib.c:327:        AsmWriteIdtr ((IA32_DESCRIPTOR *) &Idtr);
UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c:134:  AsmWriteIdtr ((IA32_DESCRIPTOR *) &IdtDescriptor);
UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c:56:        IDTR by AsmWriteIdtr().
UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c:453:  AsmWriteIdtr (&PeiS3ResumeState->Idtr);


> Yes, it does that on x86_64 / OVMF. (The feature comes from UefiCpuPkg.)
> The exception type & details (registers etc) are dumped, and even the
> offending binary file and RIP are identified in a way that allows one to
> correlate the exception with the source code.
> 
> However:
> - I have no clue if anything similar exists in / for ARM builds.
> 
> - Even if someone wants to implement such, where should (where *can*,
>  actually) the exception handler table exist at all? The addresses
>  that I listed above are backed by the (read-only) flash chip. The
>  exception handler table should be built somewhere in DRAM, no?
> 
>> If
>> not then providing a sensible initial set of vectors is even
>> more important.
> 
> Hmmm, wait a second, now grepping for CpuExceptionHandlerLib, I'm
> actually getting results from ARM packages as well. Ard's series
> resolves this library class to:
> 
> 
> CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf
> 
> Ugh, that's a null library instance; it does nothing. :( If it's any
> consolation, "ArmVExpress.dsc.inc" seems to use the same, for the
> physical platforms.
> 
> ... Hm, maybe I'm looking in the wrong place. ARM likely doesn't
> actually use CpuExceptionHandlerLib for handling CPU expcetions.
> 
> There's this code though:
> 
>  ArmPkg/Drivers/CpuDxe/AArch64/Exception.c
> 
> I think it covers exactly what you say (or at least participates in it).
> People have even submitted patches against it (see git commit 6a343fac
> for example.) I'm quite sure the feature you named is covered, but
> Olivier should be able to state authoritatively.
> 
> Thanks
> Laszlo
> 
> ------------------------------------------------------------------------------
> Slashdot TV.  
> Video for Nerds.  Stuff that matters.
> http://tv.slashdot.org/
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/edk2-devel
------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Laszlo Ersek Aug. 28, 2014, 3:22 p.m. UTC | #24
On 08/28/14 17:17, Peter Maydell wrote:
> On 28 August 2014 16:08, Laszlo Ersek <lersek@redhat.com> wrote:
>> - Even if someone wants to implement such, where should (where *can*,
>>   actually) the exception handler table exist at all? The addresses
>>   that I listed above are backed by the (read-only) flash chip. The
>>   exception handler table should be built somewhere in DRAM, no?
> 
> There's no inherent reason it needs to be in DRAM. For a
> boot loader I would expect it to be a minimal assembly
> stub that just sets up to call into C code. If you really
> need to have runtime dispatch of your exceptions you
> can do it by indirection in the C function. If all you're
> doing is "blow up and print message to UART" then you
> don't need that either, you can just have your panic
> handler live in your ROM image.
> 
> If you want to get fancier then for AArch64 (and for
> AArch32 CPUs with support for the security extensions)
> there's a CPU register you can use to put the vector
> table somewhere else than the base of RAM. But it's
> nice to have a functional vector table out of the gate
> to deal with things blowing up before you get round to
> installing a table that's somewhere else.

You're saying "put the vector table somewhere else than the base of RAM".

Address 0 that I described was guest-phys address 0, but it's flash,
it's not RAM. The base of RAM would be 1GB (0x4000_0000). I'm confused
-- where does the CPU look for the table per default? Address 0
(whatever may be there), or the base of system RAM?

Anyway this topic is out of my league :)

Thanks,
Laszlo


------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Peter Maydell Aug. 28, 2014, 3:25 p.m. UTC | #25
On 28 August 2014 16:22, Laszlo Ersek <lersek@redhat.com> wrote:
> You're saying "put the vector table somewhere else than the base of RAM".

Sorry, that was a thinko on my part. I meant "base of
physical address space".

-- PMM

------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Ard Biesheuvel Aug. 28, 2014, 3:26 p.m. UTC | #26
On 28 August 2014 16:30, Laszlo Ersek <lersek@redhat.com> wrote:
> comments below
>
> On 08/27/14 17:12, Ard Biesheuvel wrote:
>
>> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization-KVM.dsc b/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization-KVM.dsc
>> new file mode 100644
>> index 000000000000..89c5ff134b41
>> --- /dev/null
>> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization-KVM.dsc
>> @@ -0,0 +1,222 @@
>> +#
>> +#  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
>
> Good, this should be resolved with our own library instance. OK.
>
>> +
>> +  # Virtio Support
>> +  VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
>> +  VirtioMmioDeviceLib|OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf
>> +
>> +  ArmPlatformSysConfigLib|ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationSysConfigLibKVM/AArch64VirtualizationSysConfigLibKVM.inf
>
> Yes, use our own. OK.
>
>> +
>> +  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
>
> This is the hack whereby we end up needing / using "ArmPlatform.h". If
> that's the tradition in ArmPlatformPkg, I'm OK with it.
>

Yes, this is copy-paste, along with most of the rest of the file

>> +
>> +
>> +################################################################################
>> +#
>> +# 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|0x80000040
>
> This PCD is important (for debugging). I propose 0x8000004F:
>
>   # DEBUG_ERROR    0x80000000 Error
>   # DEBUG_INFO     0x00000040 Informational debug messages
>   # DEBUG_FS       0x00000008 EFI File system
>   # DEBUG_LOAD     0x00000004 Load events
>   # DEBUG_WARN     0x00000002 Warnings
>   # DEBUG_INIT     0x00000001 Initialization
>
> In addition, PcdDebugPrintErrorLevel is also set in the include file (to
> 0x8000000F), but since this setting comes after the !include directive,
> this one takes effect. I think having two settings is confusing, so
> please keep only one.
>

ok

>> +
>> +  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
>> +
>
> Whatever I understand from these seem reasonable (we discussed some of
> them before).
>
>> +  #
>> +  # 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
>> +  #
>> +  gArmPlatformTokenSpaceGuid.PcdDefaultBootDescription|L"Linux (EFI stub) on virtio31:hd0:part0"
>> +  gArmPlatformTokenSpaceGuid.PcdDefaultBootDevicePath|L"VenHw(837DCA9E-E874-4D82-B29A-23FE0E23D1E2,003E000A00000000)/HD(1,MBR,0x00000000,0x3F,0x19FC0)/Image"
>> +  gArmPlatformTokenSpaceGuid.PcdDefaultBootArgument|"root=/dev/vda2 console=ttyAMA0,38400n8 earlycon=pl011,0x9000000 uefi_debug"
>> +  gArmPlatformTokenSpaceGuid.PcdDefaultBootType|0
>
> It's impossible to set a "robust" value here, but the VenHw node at
> least should reflect the "new" format, ie. where we include the UINT64
> register block base address rather than the UINT32 instance number.
>
>> +
>> +   # 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)/VenVt100()"
>> +  gArmPlatformTokenSpaceGuid.PcdDefaultConInPaths|L"VenHw(D3987D4B-971A-435F-8CAF-4967EB627241)/Uart(38400,8,N,1)/VenVt100()"
>> +  gArmPlatformTokenSpaceGuid.PcdPlatformBootTimeOut|3
>
> Okay, looks like we managed to request VT100 terminals after all! :)
>

Well, at least I tried :-)
It doesn't really seem to make a difference, re ^H for backspace etc

>> +
>> +  #
>> +  # 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
>
> Right. As mentioned recently, I think we actually want to keep
> PcdSystemMemoryBase fixed-at-build.
>

Yep, changed that in v4

>> +
>> +  # location of the device tree blob passed by QEMU
>> +  gArmTokenSpaceGuid.PcdDeviceTreeBaseAddress|0x40000000
>> +
>> +  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
>
> Huh, I wonder if we need this! We have very similar code in
> "ArmPlatformPkg/PlatformPei/PlatformPeim.c".
>
> I do see that many ARM platforms include
> "Nt32Pkg/BootModePei/BootModePei.inf". I think they all should drop it.
>
> Well, actually, this Nt32 PEIM is *not* included in the FDF file. Which
> is correct. However, we shouldn't even build it -- remove it from the
> DSC, please.
>

ok

>> +  MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
>> +  MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf {
>> +    <LibraryClasses>
>> +      NULL|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
>> +  }
>
> Okay, I had a small heart attack here, but I'm recovering now :)
>
> I didn't understand for a moment why we needed this decompression thing.
> I was confused by my OVMF background: in OVMF, the *SEC* phase
> decompresses "stuff" that ends up carrying both PEIMs and DXE modules.
>
> Clearly this would be fatal for us here, because such decompression
> would need *some* system DRAM initialization *in SEC*, and in
> particular, writes to DRAM. And
>
> (a) that's the very PCD that we assert to be FALSE,
>
> (b) the code in InitializeMemory() and our
>     ArmPlatformInitializeSystemMemory() version works with the FD (not
>     any potentially decompressed FV!) boundaries.
>
> Then I noticed that this library was plugged into DxeIpl (DXE Initial
> Program Load) only. That's a completely different matter, and we're
> safe. In the aarch64 guest, the PEI phase will execute binaries (PEIMs)
> from NOR flash. Okay. Phew.
>
> Another strong hint is that the library class "ExtractGuidedSectionLib"
> (for which LzmaCustomDecompressLib is a "plugin") is *only* ever
> resolved to these two instances:
> - PeiExtractGuidedSectionLib
> - DxeExtractGuidedSectionLib
>
> None of these are usable in SEC; you can see the client module type
> restrictions in the LIBRARY_CLASS defines of their INF files.
>
> (See also git commit ad43bc6b for some background.)
>
> So, all's fine; I'll return to this in the FDF review, below.
>
>> +
>> +  #
>> +  # 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
>
> Yay! :)
>
> ... Actually, VirtioPciDeviceDxe should be dropped.
>
> We don't have PCI emulation yet. Even if we had it in QEMU (I got no
> idea), then we don't have a root bridge driver for it in edk2. So
> nothing will enumerate PCI devices, nothing will create PciIo protocol
> instances.
>
> Hence the VirtioPciDeviceDxe driver (a UEFI driver compliant with the
> UEFI driver model) will never install a VirtioProtocol instance on any
> handle that has a PciIo protocol instance. Simply by virtue of such a
> handle not existing.
>
> This is why we have DTB-based virtio-mmio enumeration in the platform
> driver, and why we use VirtioMmioDeviceLib.
>
> So, please drop VirtioPciDeviceDxe; we can easily add it later, if it'll
> ever make sense in aarch64 guests (and someone writes an edk2 root
> bridge driver for it).
>

ok

>> +
>> +
>> +  #
>> +  # 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..78efb8dbb100
>> --- /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
>
> Two megs, okay.
>
>> +
>> +# This one is tricky, it must be: BlockSize * NumBlocks = Size
>> +BlockSize     = 0x00001000
>> +NumBlocks     = 0x200
>> +
>
> Yes, 4K is usual.
>
>> +################################################################################
>> +#
>> +# 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.
>
> You could say "the C language doesn't favor dereferencing of NULL
> pointers" as well :)
>

Same thing :-)

>> +# So instead, put 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
>
> Awesome, thanks.
>
> And, these are the FV PCDs that we reference in
> "ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformPeiLib.c",
> function PlatformPeim():
>
>   BuildFvHob (PcdGet32(PcdFvBaseAddress), PcdGet32(PcdFvSize));
>
> This will tell DXE where to look for a firmware volume. And, in DXE, we
> *can* decompress things! Okay.
>
> BTW, the offsets here are listed relative to the start of the FD, but
> the PCDs take absolute values. Currently that means the same thing
> because the FD's BaseAddress is zero.
>
> For clarity, I'll now quote the rest of this patch out of order.
>
>> +
>> +
>> +################################################################################
>> +#
>> +# 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_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
>> +    }
>> +  }
>> +
>> +
>
> So we got, in the NOR-mapped FD file:
>
> address 0:  jump instruction to 4K, otherwise a bunch of emptiness
>             (according to erase polarity!)
>
> address 4K: a firmware volume (FVMAIN_COMPACT) with an FFS (firmware
>             volume file system) that contains the following files:
>
>             - a bunch of *uncompressed* PEIMs
>
>             - a special file called APRIORI file, prescribing dispatch
>               order for the PEI dispatcher. People always put the PCD
>               PEIM first, as I recall. That's because it needs to set up
>               the PCD database, copying the in-flash PCD DB (an
>               implicitly built FFS file) into memory (a special HOB in
>               temporary RAM), and it allows all other PEIMs to use PCDs.
>
>             - an FFS file that has a section:
>
>               - which is *compressed*, and has GUID EE4E5898...,
>                 corresponding to gLzmaCustomDecompressGuid -- this will
>                 connect the section to LzmaCustomDecompressLib above!
>
>               - and which section embeds another firmware volume, called
>                 FVMAIN (see just below), with an FFS that contains the
>                 following files:
>
>                 - a bunch of DXE modules,
>
>                 - a special file called APRIORI file, prescribing
>                   dispatch order for the DXE dispatcher. The PCD driver
>                   comes first, again.
>
> This is very nice. SEC and PEI modules are uncompressed in the FD, they
> run from NOR flash. The DXE IPL (DXE initial program load) PEIM, the
> last PEIM that runs in PEI, will decompress FVMAIN from the compressed
> FFS file section, from NOR flash to RAM, will scan the new firmware
> volume (in RAM), and then DXE modules, including the DXE_CORE, will run
> from RAM. By that time, our DTB will have been relocated and protected.
> Cool.
>
>> +[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
>
> Again, pls. drop VirtioPciDeviceDxe.
>

ok

>> +
>> +  #
>> +  # UEFI application (Shell Embedded Boot Loader)
>> +  #
>> +  INF ShellBinPkg/UefiShell/UefiShell.inf
>
> It would be nice *not* to use the prebuilt UEFI shell binary. Instead,
> we could build the UEFI shell from source. Please search OvmfPkgX64.dsc
> and OvmfPkgX64.fdf for "ShellPkg/Application/Shell/Shell.inf", and
> consider stealing what you can.
>
> This allows you to do UEFI shell development flexibly -- your develop /
> build / reboot / test cycle can now cover the UEFI shell as well. It
> also enables you to take advantage of ShellPkg commits as soon as they
> appear in the tree, no need to wait for periodic binary syncs in
> ShellBinPkg.
>

Well, to be honest, I'd prefer to do what all the other ARM kids our
doing, as that means less potential surprises for people switching
between real systems and this QEMU build.

>> +
>> +  #
>> +  # Bds
>> +  #
>> +  INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
>> +  INF ArmPlatformPkg/Bds/Bds.inf
>> +
>> +
>
> I'll just assume that the following rules have been copied verbatim from
> existent platforms:
>

indeed

>> +################################################################################
>> +#
>> +# 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
>> +  }
>> +
>
> Okay. Now back to the DSC inc file:
>
>> diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization.dsc.inc b/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization.dsc.inc
>> new file mode 100644
>> index 000000000000..67c024feb086
>> --- /dev/null
>> +++ b/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization.dsc.inc
>> @@ -0,0 +1,336 @@
>> +#
>> +#  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
>> +
>> +  PlatformPeiLib|ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformPeiLib.inf
>> +  EfiResetSystemLib|ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.inf
>
> Correct, both of these.
>
> We've now put to use all four library instances that we introduce, good.
>
>> +
>> +  # 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
>> +
>
> This part is probably not absolutely minimal, but if it works, it's
> good.
>
>> +################################################################################
>> +#
>> +# 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
>> +
>> +[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
>
> Ditto.
>
> Also, I'd prefer if each PCD was mentioned only once, across the DSC and
> the DSC.inc cumulatively, but this is really the lowest priority
> imaginable.
>

Well, the idea is more or less to put reasonable default for all virt
targets (QEMU, Xen) there, and specialize in the .dsc
But I know too little about Xen to be able to even predict where the
split would end up, so I kind of left it as I found it.

> I'm glad I ultimately forced myself to review these files. I now
> understand the flash layout, thanks to the FDF, and it's reassuring that
> it matches the assumptions that I've been operating under (and that you
> tested), wrt. the PEIMs we care about strongly executing from NOR flash,
> decompression of FVs, etc.
>
> I feel great about this work. Looking forward to version 4. :)
>

Thanks,
Ard.

------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Laszlo Ersek Aug. 28, 2014, 3:46 p.m. UTC | #27
On 08/28/14 17:17, Peter Maydell wrote:
> On 28 August 2014 16:16, Laszlo Ersek <lersek@redhat.com> wrote:
>> On 08/28/14 16:59, Ard Biesheuvel wrote:
>>> However, putting a vector table in that particular place is
>>> troublesome, as the whole point of having the region is to avoid
>>> putting a Firmware Volume (FV) there. And having to code the whole
>>> vector table in hex inside the DATA = { } is not a great prospect
>>> either.
> 
> This just seems like a flaw in UEFI to me. You really need to
> be able to write bits of custom assembly and data to low memory.

I think I can agree that this may be a limitation of the edk2 build
system (not "UEFI" in general). I have read complaints before that DATA
= { } regions in FDF files are a pain to format, especially in an
automated way.

As a workaround, sometimes people write Python scripts (which they
commit to the tree) that process custom source files (which they also
commit to the tree). These source files can be assembly language files
that are not covered by the normal edk2 build process. The python
script(s) can invoke custom assemblers, binutils, hexdump as well, and
the output can be some FDF.inc file (which is also committed to the tree).

The "main" FDF file can then !include this generated FDF.inc.

In these cases the development process goes like:
- if you need to update your custom code, update the assembly file,
- regenerate the FDF.inc by manually re-running the python script,
- commit the changes together (changed assembly src + FDF.inc),
- the next build will pick up the new FDF.inc.

This is not "ideal" (as in, "fully automated"), but it works; there have
been examples.

>From time to time BaseTools are extended to cover such "extras"
natively. Specifically, this use case seems new to me.

But, certainly doable, as long as one were to write a suitable generator
in Python, and of course the assembly code in question.

>> I think that the exception vector table simply doesn't *belong* in the
>> flash.
> 
> I don't understand that. In the flash seems entirely reasonable
> to me...

I was simply wrong, probably.

Thanks
Laszlo


------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Andrew Fish Aug. 28, 2014, 5:35 p.m. UTC | #28
On Aug 28, 2014, at 8:46 AM, Laszlo Ersek <lersek@redhat.com> wrote:

> On 08/28/14 17:17, Peter Maydell wrote:
>> On 28 August 2014 16:16, Laszlo Ersek <lersek@redhat.com> wrote:
>>> On 08/28/14 16:59, Ard Biesheuvel wrote:
>>>> However, putting a vector table in that particular place is
>>>> troublesome, as the whole point of having the region is to avoid
>>>> putting a Firmware Volume (FV) there. And having to code the whole
>>>> vector table in hex inside the DATA = { } is not a great prospect
>>>> either.
>> 
>> This just seems like a flaw in UEFI to me. You really need to
>> be able to write bits of custom assembly and data to low memory.
> 

It is the ARM architecture that places the reset vector at exception/vector zero. In x86 it is at the magic address, 0xFFFFFFF0, and not associated with exceptions/interrupts. 

The PI spec reserves the 1st 16 bytes of the FV, the ZeroVector[], for use by the build system if needed for the ARM reset vector. 

The edk2 system will patch a branch to the entry point of the SEC module into the ZeroVector of the FV header if the FV contains a SEC module. 

When you have memory, or temporary PEI memory. Having memory is also known as you are able to run C code. At this point you can relocate the vectors and handle exceptions. 

You can always offset the FV into the FD, and make the beginning of the FD a vector table. As long as the reset vector branches to the start of the FV (which will branch to the start of SEC) it will work just fine. 

> I think I can agree that this may be a limitation of the edk2 build
> system (not "UEFI" in general). I have read complaints before that DATA
> = { } regions in FDF files are a pain to format, especially in an
> automated way.
> 
> As a workaround, sometimes people write Python scripts (which they
> commit to the tree) that process custom source files (which they also
> commit to the tree). These source files can be assembly language files
> that are not covered by the normal edk2 build process. The python
> script(s) can invoke custom assemblers, binutils, hexdump as well, and
> the output can be some FDF.inc file (which is also committed to the tree).
> 
> The "main" FDF file can then !include this generated FDF.inc.
> 
> In these cases the development process goes like:
> - if you need to update your custom code, update the assembly file,
> - regenerate the FDF.inc by manually re-running the python script,
> - commit the changes together (changed assembly src + FDF.inc),
> - the next build will pick up the new FDF.inc.
> 

I don’t really understand what all this is for? If some one could explain the requirements we could probably add a feature to the edk2 build system to fix this.

To see what the build system does today look at: https://svn.code.sf.net/p/edk2/code/trunk/edk2/BaseTools/Source/C/GenFv/GenFvInternalLib.c

EFI_STATUS
UpdateArmResetVectorIfNeeded (
  IN MEMORY_FILE            *FvImage,
  IN FV_INFO                *FvInfo
  )
/*++

Routine Description:
  This parses the FV looking for SEC and patches that address into the 
  beginning of the FV header.

  For ARM32 the reset vector is at 0x00000000 or 0xFFFF0000.
  For AArch64 the reset vector is at 0x00000000.

  This would commonly map to the first entry in the ROM. 
  ARM32 Exceptions:
  Reset            +0    
  Undefined        +4
  SWI              +8
  Prefetch Abort   +12
  Data Abort       +16
  IRQ              +20
  FIQ              +24

  We support two schemes on ARM.
  1) Beginning of the FV is the reset vector
  2) Reset vector is data bytes FDF file and that code branches to reset vector 
    in the beginning of the FV (fixed size offset).

  Need to have the jump for the reset vector at location zero.
  We also need to store the address or PEI (if it exists).
  We stub out a return from interrupt in case the debugger 
   is using SWI (not done for AArch64, not enough space in struct).
  The optional entry to the common exception handler is 
   to support full featured exception handling from ROM and is currently 
    not support by this tool.


Thanks,

Andrew Fish

> This is not "ideal" (as in, "fully automated"), but it works; there have
> been examples.
> 
>> From time to time BaseTools are extended to cover such "extras"
> natively. Specifically, this use case seems new to me.
> 
> But, certainly doable, as long as one were to write a suitable generator
> in Python, and of course the assembly code in question.
> 
>>> I think that the exception vector table simply doesn't *belong* in the
>>> flash.
>> 
>> I don't understand that. In the flash seems entirely reasonable
>> to me...
> 
> I was simply wrong, probably.
> 
> Thanks
> Laszlo
> 
> 
> ------------------------------------------------------------------------------
> Slashdot TV.  
> Video for Nerds.  Stuff that matters.
> http://tv.slashdot.org/
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/edk2-devel


------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Laszlo Ersek Aug. 28, 2014, 7:57 p.m. UTC | #29
On 08/28/14 19:35, Andrew Fish wrote:
> 
> On Aug 28, 2014, at 8:46 AM, Laszlo Ersek <lersek@redhat.com> wrote:
> 
>> On 08/28/14 17:17, Peter Maydell wrote:
>>> On 28 August 2014 16:16, Laszlo Ersek <lersek@redhat.com> wrote:
>>>> On 08/28/14 16:59, Ard Biesheuvel wrote:
>>>>> However, putting a vector table in that particular place is
>>>>> troublesome, as the whole point of having the region is to avoid
>>>>> putting a Firmware Volume (FV) there. And having to code the whole
>>>>> vector table in hex inside the DATA = { } is not a great prospect
>>>>> either.
>>>
>>> This just seems like a flaw in UEFI to me. You really need to
>>> be able to write bits of custom assembly and data to low memory.
>>
> 

> It is the ARM architecture that places the reset vector at
> exception/vector zero. In x86 it is at the magic address, 0xFFFFFFF0,
> and not associated with exceptions/interrupts.
> 
> The PI spec reserves the 1st 16 bytes of the FV, the ZeroVector[],
> for use by the build system if needed for the ARM reset vector.
> 
> The edk2 system will patch a branch to the entry point of the SEC
> module into the ZeroVector of the FV header if the FV contains a SEC
> module.
> 
> When you have memory, or temporary PEI memory. Having memory is also
> known as you are able to run C code. At this point you can relocate
> the vectors and handle exceptions.
> 
> You can always offset the FV into the FD, and make the beginning of
> the FD a vector table. As long as the reset vector branches to the
> start of the FV (which will branch to the start of SEC) it will work
> just fine.
> 

>> I think I can agree that this may be a limitation of the edk2 build
>> system (not "UEFI" in general). I have read complaints before that DATA
>> = { } regions in FDF files are a pain to format, especially in an
>> automated way.
>>
>> As a workaround, sometimes people write Python scripts (which they
>> commit to the tree) that process custom source files (which they also
>> commit to the tree). These source files can be assembly language files
>> that are not covered by the normal edk2 build process. The python
>> script(s) can invoke custom assemblers, binutils, hexdump as well, and
>> the output can be some FDF.inc file (which is also committed to the tree).
>>
>> The "main" FDF file can then !include this generated FDF.inc.
>>
>> In these cases the development process goes like:
>> - if you need to update your custom code, update the assembly file,
>> - regenerate the FDF.inc by manually re-running the python script,
>> - commit the changes together (changed assembly src + FDF.inc),
>> - the next build will pick up the new FDF.inc.
>>
> 

> I don’t really understand what all this is for? If some one could
> explain the requirements we could probably add a feature to the edk2
> build system to fix this.
> 
> To see what the build system does today look at:
> https://svn.code.sf.net/p/edk2/code/trunk/edk2/BaseTools/Source/C/GenFv/GenFvInternalLib.c
> 
> EFI_STATUS
> UpdateArmResetVectorIfNeeded (
>   IN MEMORY_FILE            *FvImage,
>   IN FV_INFO                *FvInfo
>   )
> /*++
> 
> Routine Description:
>   This parses the FV looking for SEC and patches that address into the 
>   beginning of the FV header.
> 
>   For ARM32 the reset vector is at 0x00000000 or 0xFFFF0000.
>   For AArch64 the reset vector is at 0x00000000.
> 
>   This would commonly map to the first entry in the ROM. 
>   ARM32 Exceptions:
>   Reset            +0    
>   Undefined        +4
>   SWI              +8
>   Prefetch Abort   +12
>   Data Abort       +16
>   IRQ              +20
>   FIQ              +24
> 
>   We support two schemes on ARM.
>   1) Beginning of the FV is the reset vector
>   2) Reset vector is data bytes FDF file and that code branches to reset vector 
>     in the beginning of the FV (fixed size offset).
> 
>   Need to have the jump for the reset vector at location zero.
>   We also need to store the address or PEI (if it exists).
>   We stub out a return from interrupt in case the debugger 
>    is using SWI (not done for AArch64, not enough space in struct).
>   The optional entry to the common exception handler is 
>    to support full featured exception handling from ROM and is currently 
>     not support by this tool.

The FDF under review follows exactly scheme 2. The FD starts with a DATA
region that starts with a manually encoded branch instruction to 0x1000.
The DATA region encodes this branch instruction in 4 bytes, and the rest
(4092 byes) come from the ErasePolarity-matching padding.

The FV is indeed offset into the FD with 0x1000 bytes, starting right
after the DATA region.

As you say, the build system (apparently) patches the start of the FV
itself (which is located at offset 0x1000 in the FD) so that it branches
to the SEC entry point. Hence I think this "double trampoline" that you
described is exactly the case.

What Peter suggested (I think) is that we build a complete exception
vector table in those 4092 bytes, past the 4-byte long reset vector at
0x0. And, in addition to the exception vector table, even a simple
exception handler routine should be implemented there (in assembly of
course), referenced by the vectors, that dumps the exception details to
the virtual serial port (or some QEMU-specific MMIO debug register etc).

Since encoding such stuff manually in a DATA = { ... } region in the FDF
file is messy, I proposed a python script that assembles (with external
tools of course) a standalone assembly file (which implements the vector
table and the exception handler), hexdumps the binary output, wraps it
in a DATA = { ... } "shell", and saves the output in an FDF include
file. Then, the main FDF file would not contain the current DATA = { ...
} block (with just the 4-byte b insn to 0x1000), it would include the
complete DATA block from the include file that the python script
generated, and that contains the hexdump of the complete vector table +
the assembled exception handler.

This would allow (very basic) exception handling while running from NOR
flash.

Of course temporary RAM becomes available very soon, so the vector table
could be set up in that temporary RAM quite early. (... Perhaps in code
that is shared by all of the ARM platforms.)

... I think such a feature is useful to investigate, but very much out
of scope for this series.

Thanks,
Laszlo


------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Laszlo Ersek Aug. 28, 2014, 8:19 p.m. UTC | #30
On 08/28/14 17:26, Ard Biesheuvel wrote:
> On 28 August 2014 16:30, Laszlo Ersek <lersek@redhat.com> wrote:
>> comments below
>>
>> On 08/27/14 17:12, Ard Biesheuvel wrote:

>>> +   # 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)/VenVt100()"
>>> +  gArmPlatformTokenSpaceGuid.PcdDefaultConInPaths|L"VenHw(D3987D4B-971A-435F-8CAF-4967EB627241)/Uart(38400,8,N,1)/VenVt100()"
>>> +  gArmPlatformTokenSpaceGuid.PcdPlatformBootTimeOut|3
>>
>> Okay, looks like we managed to request VT100 terminals after all! :)
>>
> 
> Well, at least I tried :-)
> It doesn't really seem to make a difference, re ^H for backspace etc

Something for later then. I think this is debuggable.

Just a quick idea: have you tried reinitializing your variable store?
See InitializeConsole() in "ArmPlatformPkg/Bds/Bds.c".

I'd sprinkle the following functions with DEBUG()s:

InitializeConsole() [ArmPlatformPkg/Bds/Bds.c]
  GetConsoleDevicePathFromVariable()
  InitializeConsolePipe()

In particular, the following call chain:

InitializeConsole() [ArmPlatformPkg/Bds/Bds.c]
  InitializeConsolePipe()
    BdsConnectDevicePath() [ArmPkg/Library/BdsLib/BdsFilePath.c]
      BdsConnectAndUpdateDevicePath()
        gBS->ConnectController()

should terminate, indirectly, in

TerminalDriverBindingStart()
[MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c]
  BuildTerminalDevpath()

where BuildTerminalDevpath() should see the VT100 type (gEfiVT100Guid).

Anyway, this is certainly for later.


>>> +
>>> +  #
>>> +  # UEFI application (Shell Embedded Boot Loader)
>>> +  #
>>> +  INF ShellBinPkg/UefiShell/UefiShell.inf
>>
>> It would be nice *not* to use the prebuilt UEFI shell binary. Instead,
>> we could build the UEFI shell from source. Please search OvmfPkgX64.dsc
>> and OvmfPkgX64.fdf for "ShellPkg/Application/Shell/Shell.inf", and
>> consider stealing what you can.
>>
>> This allows you to do UEFI shell development flexibly -- your develop /
>> build / reboot / test cycle can now cover the UEFI shell as well. It
>> also enables you to take advantage of ShellPkg commits as soon as they
>> appear in the tree, no need to wait for periodic binary syncs in
>> ShellBinPkg.
>>
> 
> Well, to be honest, I'd prefer to do what all the other ARM kids our
> doing, as that means less potential surprises for people switching
> between real systems and this QEMU build.

That's a valid point.

>> Also, I'd prefer if each PCD was mentioned only once, across the DSC and
>> the DSC.inc cumulatively, but this is really the lowest priority
>> imaginable.
>>
> 
> Well, the idea is more or less to put reasonable default for all virt
> targets (QEMU, Xen) there, and specialize in the .dsc
> But I know too little about Xen to be able to even predict where the
> split would end up, so I kind of left it as I found it.

I understand; thanks for the explanation.

Laszlo


------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Peter Maydell Aug. 28, 2014, 9:28 p.m. UTC | #31
On 28 August 2014 20:57, Laszlo Ersek <lersek@redhat.com> wrote:
> The FDF under review follows exactly scheme 2. The FD starts with a DATA
> region that starts with a manually encoded branch instruction to 0x1000.
> The DATA region encodes this branch instruction in 4 bytes, and the rest
> (4092 byes) come from the ErasePolarity-matching padding.
>
> The FV is indeed offset into the FD with 0x1000 bytes, starting right
> after the DATA region.
>
> As you say, the build system (apparently) patches the start of the FV
> itself (which is located at offset 0x1000 in the FD) so that it branches
> to the SEC entry point. Hence I think this "double trampoline" that you
> described is exactly the case.
>
> What Peter suggested (I think) is that we build a complete exception
> vector table in those 4092 bytes, past the 4-byte long reset vector at
> 0x0. And, in addition to the exception vector table, even a simple
> exception handler routine should be implemented there (in assembly of
> course), referenced by the vectors, that dumps the exception details to
> the virtual serial port (or some QEMU-specific MMIO debug register etc).

Well, it's up to you how much you want to put in assembly and exactly
where you want to put the assembly. You could have all the vector table
entries be single-instruction jumps into your FV, same way you
deal with the reset vector. I just expected to see *something* valid in the
other entries in the initial vector table. Most of the rest of my remarks
are based on the assumption that you're generating the start of your
binary blob in the obvious way, ie by running something through
an assembler to get an object file and eventually a hex blob that
your build system assembles into the start of the rom image.

-- PMM

------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
Ard Biesheuvel Aug. 29, 2014, 11:38 a.m. UTC | #32
On 28 August 2014 23:28, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 28 August 2014 20:57, Laszlo Ersek <lersek@redhat.com> wrote:
>> The FDF under review follows exactly scheme 2. The FD starts with a DATA
>> region that starts with a manually encoded branch instruction to 0x1000.
>> The DATA region encodes this branch instruction in 4 bytes, and the rest
>> (4092 byes) come from the ErasePolarity-matching padding.
>>
>> The FV is indeed offset into the FD with 0x1000 bytes, starting right
>> after the DATA region.
>>
>> As you say, the build system (apparently) patches the start of the FV
>> itself (which is located at offset 0x1000 in the FD) so that it branches
>> to the SEC entry point. Hence I think this "double trampoline" that you
>> described is exactly the case.
>>
>> What Peter suggested (I think) is that we build a complete exception
>> vector table in those 4092 bytes, past the 4-byte long reset vector at
>> 0x0. And, in addition to the exception vector table, even a simple
>> exception handler routine should be implemented there (in assembly of
>> course), referenced by the vectors, that dumps the exception details to
>> the virtual serial port (or some QEMU-specific MMIO debug register etc).
>
> Well, it's up to you how much you want to put in assembly and exactly
> where you want to put the assembly. You could have all the vector table
> entries be single-instruction jumps into your FV, same way you
> deal with the reset vector. I just expected to see *something* valid in the
> other entries in the initial vector table. Most of the rest of my remarks
> are based on the assumption that you're generating the start of your
> binary blob in the obvious way, ie by running something through
> an assembler to get an object file and eventually a hex blob that
> your build system assembles into the start of the rom image.
>

There is no vector table at the start of the now 0x1000 upward shifted
image either, so it is not a matter of putting a bunch of 'b 0x1000'
instructions at the right offsets (depending on whether you are
targeting ARM or AArch64). However, the first module that executes
installs a vector table by setting VBAR in its CEntryPoint() function,
ie. the entry point that runs immediately after setting up the
environment in assembler, and we have already identified that
exceptions taken before that won't nop-slide into the normal entry
point and go unnoticed.

Note that the above applies equally to all supported ARM platforms in
Tianocore, so I think having the DATA = { } with the branches in hex
is the most suitable solution, at least for now.
Andrew Fish Aug. 29, 2014, 6:06 p.m. UTC | #33
On Aug 29, 2014, at 4:38 AM, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:

> There is no vector table at the start of the now 0x1000 upward shifted
> image either, so it is not a matter of putting a bunch of 'b 0x1000'
> instructions at the right offsets (depending on whether you are
> targeting ARM or AArch64). However, the first module that executes
> installs a vector table by setting VBAR in its CEntryPoint() function,
> ie. the entry point that runs immediately after setting up the
> environment in assembler, and we have already identified that
> exceptions taken before that won't nop-slide into the normal entry
> point and go unnoticed.
> 
> Note that the above applies equally to all supported ARM platforms in
> Tianocore, so I think having the DATA = { } with the branches in hex
> is the most suitable solution, at least for now.

I’m not opposed to the DATA = {} solution as long as it is just a template that anyone can use. It is not a good way to write code. 

The 1st UINTN in the FV Header ZeroVector[] is a branch to _ModuleEntryPoint. I’m wondering if we should make the 2nd UINTN the address of _ModuleEntryPoint. Then we could make _ModuleEntryPoint the vector table.  If _ModuleEntryPoint is a vector table the branch to _ModuleEntryPoint, would just branch to the reset code in the SEC. Thus the DATA = {} code can branch to the start of the FV for the reset vector. For exceptions you could get the _ModuleEntryPoint address from the start of the FV + sizeof (UINTN). You can then add the vector + sizeof(UINTN) to that address to dispatch the exception handler in the SEC code. The DATA = {} code would be write once, and never have to change again. 

If this is useful we could update the build tools to also patch the _ModuleEntryPoint in the 2nd entry in the FV header zero vector. 

Given how simple the ARM instruction set is it may also be possible to extract the offset from the current branch instruction and not require any tools changes. 

Thanks,

Andrew Fish
------------------------------------------------------------------------------
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..89c5ff134b41
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization-KVM.dsc
@@ -0,0 +1,222 @@ 
+#
+#  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|0x80000040
+
+  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
+
+  #
+  # 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
+  #
+  gArmPlatformTokenSpaceGuid.PcdDefaultBootDescription|L"Linux (EFI stub) on virtio31:hd0:part0"
+  gArmPlatformTokenSpaceGuid.PcdDefaultBootDevicePath|L"VenHw(837DCA9E-E874-4D82-B29A-23FE0E23D1E2,003E000A00000000)/HD(1,MBR,0x00000000,0x3F,0x19FC0)/Image"
+  gArmPlatformTokenSpaceGuid.PcdDefaultBootArgument|"root=/dev/vda2 console=ttyAMA0,38400n8 earlycon=pl011,0x9000000 uefi_debug"
+  gArmPlatformTokenSpaceGuid.PcdDefaultBootType|0
+
+   # 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)/VenVt100()"
+  gArmPlatformTokenSpaceGuid.PcdDefaultConInPaths|L"VenHw(D3987D4B-971A-435F-8CAF-4967EB627241)/Uart(38400,8,N,1)/VenVt100()"
+  gArmPlatformTokenSpaceGuid.PcdPlatformBootTimeOut|3
+
+  #
+  # 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
+
+  # location of the device tree blob passed by QEMU
+  gArmTokenSpaceGuid.PcdDeviceTreeBaseAddress|0x40000000
+
+  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..78efb8dbb100
--- /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, put 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..67c024feb086
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/AArch64Virtualization.dsc.inc
@@ -0,0 +1,336 @@ 
+#
+#  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
+
+  PlatformPeiLib|ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformPeiLib.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
+
+[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..464829607871
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdt.inf
@@ -0,0 +1,61 @@ 
+## @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
+  gArmTokenSpaceGuid.PcdDeviceTreeBaseAddress
+
+[Protocols]
+
+[Depex]
+  TRUE
diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdtDxe.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdtDxe.c
new file mode 100644
index 000000000000..1ad9e929ae62
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Driver/VirtFdtDxe.c
@@ -0,0 +1,249 @@ 
+/** @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>
+
+CONST UINT32 mUint32Max = 0xFFFFFFFFU;
+
+#pragma pack (1)
+typedef struct {
+  VENDOR_DEVICE_PATH                  Vendor;
+  UINT64                              PhysBase;
+  EFI_DEVICE_PATH_PROTOCOL            End;
+} VIRTIO_TRANSPORT_DEVICE_PATH;
+#pragma pack ()
+
+typedef enum {
+  PropertyTypeUnknown,
+  PropertyTypeGic,
+  PropertyTypeRtc,
+  PropertyTypeVirtio,
+  PropertyTypeUart,
+  PropertyTypeTimer,
+} PROPERTY_TYPE;
+
+typedef struct {
+  PROPERTY_TYPE Type;
+  CHAR8         Compatible[20];
+} PROPERTY;
+
+STATIC CONST PROPERTY CompatibleProperties[] = {
+  { PropertyTypeGic,     "arm,cortex-a15-gic"  },
+  { PropertyTypeRtc,     "arm,pl031"           },
+  { PropertyTypeVirtio,  "virtio,mmio"         },
+  { PropertyTypeUart,    "arm,pl011"           },
+  { PropertyTypeTimer,   "arm,armv7-timer"     },
+  { PropertyTypeTimer,   "arm,armv8-timer"     },
+  { PropertyTypeUnknown, ""                    }
+};
+
+typedef struct {
+  UINT32  Type;
+  UINT32  Number;
+  UINT32  Flags;
+} INTERRUPT_PROP;
+
+STATIC
+PROPERTY_TYPE
+GetTypeFromNode (
+  IN CONST CHAR8 *NodeType,
+  IN UINTN       Size
+  )
+{
+  CONST CHAR8 *Compatible;
+
+  //
+  // A 'compatible' node may contain a sequence of NULL terminated
+  // compatible strings so check each one
+  //
+  for (Compatible = NodeType; Compatible < NodeType + Size && *Compatible;
+       Compatible += 1 + AsciiStrLen (Compatible)) {
+
+    CONST PROPERTY *CompProp;
+
+    for (CompProp = CompatibleProperties; CompProp->Compatible[0]; CompProp++) {
+      if (AsciiStrCmp (CompProp->Compatible, Compatible) == 0) {
+        return CompProp->Type;
+      }
+    }
+  }
+  return PropertyTypeUnknown;
+}
+
+EFI_STATUS
+EFIAPI
+InitializeVirtFdtDxe (
+  IN EFI_HANDLE           ImageHandle,
+  IN EFI_SYSTEM_TABLE     *SystemTable
+  )
+{
+  VOID        *DeviceTreeBase;
+  INT32        Node, Prev;
+  EFI_STATUS   Status;
+
+  DeviceTreeBase = (VOID *)PcdGet64 (PcdDeviceTreeBaseAddress);
+  ASSERT (DeviceTreeBase != NULL);
+
+  if (fdt_check_header (DeviceTreeBase) != 0) {
+    DEBUG ((EFI_D_ERROR, "%a: No DTB found @ 0x%Lx\n", __FUNCTION__, DeviceTreeBase));
+    return EFI_NOT_FOUND;
+  }
+
+  Status = gBS->InstallConfigurationTable (&gFdtTableGuid, DeviceTreeBase);
+  ASSERT_EFI_ERROR (Status);
+
+  DEBUG ((EFI_D_INFO, "%a: DTB @ 0x%p\n", __FUNCTION__, DeviceTreeBase));
+
+  //
+  // Now enumerate the nodes and install peripherals that we are interested in,
+  // i.e., GIC, RTC and virtio MMIO nodes
+  //
+  for (Prev = 0;; Prev = Node) {
+    CONST CHAR8                   *Type;
+    INT32                          Len;
+    PROPERTY_TYPE                  PropType;
+    CONST VOID                    *RegProp;
+    VIRTIO_TRANSPORT_DEVICE_PATH  *DevicePath;
+    EFI_HANDLE                     Handle;
+    UINT64                         RegBase;
+    UINT64                         DistBase, CpuBase;
+    CONST INTERRUPT_PROP          *InterruptProp;
+    INT32                          SecIntrNum, IntrNum, VirtIntrNum, HypIntrNum;
+
+    Node = fdt_next_node (DeviceTreeBase, Prev, NULL);
+    if (Node < 0)
+      break;
+
+    Type = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len);
+    if (Type == NULL)
+      continue;
+
+    PropType = GetTypeFromNode (Type, Len);
+    if (PropType == PropertyTypeUnknown)
+      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 (DeviceTreeBase, Node, "reg", &Len);
+    ASSERT (RegProp != NULL || PropType == PropertyTypeTimer);
+
+    switch (PropType) {
+      
+    case PropertyTypeVirtio:
+      ASSERT (Len == 16);
+      //
+      // Create a unique device path for this transport on the fly
+      //
+      RegBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);
+      DevicePath = (VIRTIO_TRANSPORT_DEVICE_PATH *)CreateDeviceNode (
+                                    HARDWARE_DEVICE_PATH,
+                                    HW_VENDOR_DP,
+                                    sizeof (VIRTIO_TRANSPORT_DEVICE_PATH));
+
+      CopyMem (&DevicePath->Vendor.Guid, &gEfiCallerIdGuid, sizeof (EFI_GUID));
+      DevicePath->PhysBase = RegBase;
+      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, "%a: Failed to install the EFI_DEVICE_PATH protocol on a new handle\n",
+               __FUNCTION__));
+        break;
+      }
+
+      Status = VirtioMmioInstallDevice (RegBase, Handle);
+      if (EFI_ERROR (Status))
+        DEBUG ((EFI_D_ERROR, "%a: Failed to install VirtIO transport @ 0x%Lx on handle %p\n",
+                __FUNCTION__, RegBase, Handle));
+      break;
+
+    case PropertyTypeGic:
+      ASSERT (Len == 32);
+
+      DistBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);
+      CpuBase = fdt64_to_cpu (((UINT64 *)RegProp)[2]);
+      ASSERT (DistBase < mUint32Max);
+      ASSERT (CpuBase < mUint32Max);
+
+      PcdSet32 (PcdGicDistributorBase, (UINT32)DistBase);
+      PcdSet32 (PcdGicInterruptInterfaceBase, (UINT32)CpuBase);
+
+      DEBUG ((EFI_D_INFO, "Found GIC @ 0x%x/0x%x\n", DistBase, CpuBase));
+      break;
+
+    case PropertyTypeRtc:
+      ASSERT (Len == 16);
+      
+      RegBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);
+      ASSERT (RegBase < mUint32Max);
+
+      PcdSet32 (PcdPL031RtcBase, (UINT32)RegBase);
+
+      DEBUG ((EFI_D_INFO, "Found PL031 RTC @ 0x%x\n", RegBase));
+      break;
+
+    case PropertyTypeTimer:
+
+      //
+      // - interrupts : Interrupt list for secure, non-secure, virtual and
+      //  hypervisor timers, in that order.
+      //
+      InterruptProp = fdt_getprop (DeviceTreeBase, Node, "interrupts", &Len);
+      ASSERT (Len == 48);
+
+      SecIntrNum = fdt32_to_cpu (InterruptProp[0].Number)
+                   + (InterruptProp[0].Type ? 16 : 0);
+      IntrNum = fdt32_to_cpu (InterruptProp[1].Number)
+                + (InterruptProp[1].Type ? 16 : 0);
+      VirtIntrNum = fdt32_to_cpu (InterruptProp[2].Number)
+                    + (InterruptProp[2].Type ? 16 : 0);
+      HypIntrNum = fdt32_to_cpu (InterruptProp[3].Number)
+                   + (InterruptProp[3].Type ? 16 : 0);
+      
+      DEBUG ((EFI_D_INFO, "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..5a74456d123e
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Include/Platform/KVM/ArmPlatform.h
@@ -0,0 +1,27 @@ 
+/** @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
+
+#endif
diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/AArch64KVMLib.inf b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/AArch64KVMLib.inf
new file mode 100644
index 000000000000..b30d70f3a1ed
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/AArch64KVMLib.inf
@@ -0,0 +1,57 @@ 
+#/* @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
+  gArmPlatformTokenSpaceGuid.PcdSystemMemoryInitializeInSec
+
+[Pcd]
+  gArmTokenSpaceGuid.PcdSystemMemoryBase
+  gArmTokenSpaceGuid.PcdSystemMemorySize
+  gArmTokenSpaceGuid.PcdDeviceTreeBaseAddress
+
+[FixedPcd]
+  gArmTokenSpaceGuid.PcdArmPrimaryCoreMask
+  gArmTokenSpaceGuid.PcdArmPrimaryCore
+
+  gArmPlatformTokenSpaceGuid.PcdCoreCount
+  gArmTokenSpaceGuid.PcdFdBaseAddress
+  gArmTokenSpaceGuid.PcdFdSize
diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVM.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVM.c
new file mode 100644
index 000000000000..cd9edfe5138b
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVM.c
@@ -0,0 +1,143 @@ 
+/** @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
+  )
+{
+  //
+  // We are relying on ArmPlatformInitializeSystemMemory () being called from
+  // InitializeMemory (), which only occurs if the following feature is disabled
+  //
+  ASSERT (!FeaturePcdGet (PcdSystemMemoryInitializeInSec));
+  return RETURN_SUCCESS;
+}
+
+/**
+  Initialize the system (or sometimes called permanent) memory
+
+  This memory is generally represented by the DRAM.
+
+**/
+VOID
+ArmPlatformInitializeSystemMemory (
+  VOID
+  )
+{
+  VOID   *DeviceTreeBase;
+  INT32   Node, Prev;
+  UINT64  NewBase = 0;
+  UINT64  NewSize = 0;
+
+  DeviceTreeBase = (VOID *)PcdGet64 (PcdDeviceTreeBaseAddress);
+  ASSERT (DeviceTreeBase != NULL);
+
+  //
+  // Make sure we have a valid device tree blob at the base of DRAM
+  //
+  if (fdt_check_header (DeviceTreeBase) != 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 (DeviceTreeBase, Prev, NULL);
+    if (Node < 0)
+      return;
+
+    Type = fdt_getprop (DeviceTreeBase, Node, "device_type", &Len);
+    if (Type && AsciiStrnCmp (Type, "memory", Len) == 0) {
+      CONST UINT64 *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 (DeviceTreeBase, Node, "reg", &Len);
+      if (RegProp != 0 && Len == (2 * sizeof (UINT64))) {
+
+        NewBase = fdt64_to_cpu (RegProp[0]);
+        NewSize = fdt64_to_cpu (RegProp[1]);
+
+        PcdSet64 (PcdSystemMemoryBase, NewBase);
+        PcdSet64 (PcdSystemMemorySize, NewSize);
+
+        DEBUG ((EFI_D_INFO, "KVM: System RAM @ 0x%lx - 0x%lx\n",
+           NewBase, NewBase + NewSize - 1));
+      } else {
+        DEBUG ((EFI_D_ERROR, "KVM: Failed to parse FDT memory node\n"));
+      }
+      break;
+    }
+  }
+  //
+  // We need to make sure that the machine we are running on has at least
+  // 128 MB of memory configured, and does not run from shadowed NOR. This
+  // prevents the device tree at base of DRAM from getting clobbered before we
+  // have a chance of marking its location as reserved or moving it out of the
+  // way.
+  //
+  ASSERT (NewSize >= SIZE_128MB);
+  ASSERT ((UINT64)PcdGet32 (PcdFdBaseAddress) + (UINT64)PcdGet32 (PcdFdSize) <= NewBase
+          || (UINT64)PcdGet32 (PcdFdBaseAddress) >= NewBase + NewSize);
+}
+
+VOID
+ArmPlatformGetPlatformPpiList (
+  OUT UINTN                   *PpiListSize,
+  OUT EFI_PEI_PPI_DESCRIPTOR  **PpiList
+  )
+{
+  *PpiListSize = 0;
+  *PpiList = NULL;
+}
diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMHelper.S b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMHelper.S
new file mode 100644
index 000000000000..af028038b4a6
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMHelper.S
@@ -0,0 +1,86 @@ 
+#
+#  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_EXPORT(ArmGetPhysAddrTop)
+
+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
+
+//EFI_PHYSICAL_ADDRESS
+//GetPhysAddrTop (
+//  VOID
+//  );
+ASM_PFX(ArmGetPhysAddrTop):
+  mrs   x0, id_aa64mmfr0_el1
+  adr   x1, .LPARanges
+  and   x0, x0, #7
+  ldrb  w1, [x1, x0]
+  mov   x0, #1
+  lsl   x0, x0, x1
+  ret
+.LPARanges:
+  .byte 32, 36, 40, 42, 44, 48, -1, -1
+
+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..f1ea66468027
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/AArch64VirtualizationLibKVM/KVMMem.c
@@ -0,0 +1,102 @@ 
+/** @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
+
+EFI_PHYSICAL_ADDRESS
+ArmGetPhysAddrTop (
+  VOID
+  );
+
+/**
+  Return the Virtual Memory Map of your platform
+
+  This Virtual Memory Map is used by MemoryInitPei Module to initialize the MMU
+  on your platform.
+
+  @param[out]   VirtualMemoryMap    Array of ARM_MEMORY_REGION_DESCRIPTOR 
+                                    describing a Physical-to-Virtual Memory
+                                    mapping. This array must be ended by a
+                                    zero-filled entry
+
+**/
+VOID
+ArmPlatformGetVirtualMemoryMap (
+  IN ARM_MEMORY_REGION_DESCRIPTOR** VirtualMemoryMap
+  )
+{
+  ARM_MEMORY_REGION_ATTRIBUTES  CacheAttributes;
+  ARM_MEMORY_REGION_DESCRIPTOR  *VirtualMemoryTable;
+
+  ASSERT (VirtualMemoryMap != NULL);
+
+  VirtualMemoryTable = AllocatePages (EFI_SIZE_TO_PAGES (
+                                     sizeof (ARM_MEMORY_REGION_DESCRIPTOR)
+                                     * MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS));
+  if (VirtualMemoryTable == NULL) {
+    DEBUG ((EFI_D_ERROR, "%a: Error: Failed AllocatePages()\n", __FUNCTION__));
+    return;
+  }
+
+  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_INFO, "%a: Dumping System DRAM Memory Map:\n"
+      "\tPhysicalBase: 0x%lX\n"
+      "\tVirtualBase: 0x%lX\n"
+      "\tLength: 0x%lX\n",
+      __FUNCTION__,
+      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       = ArmGetPhysAddrTop () - 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/PlatformPei/PlatformPeiLib.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformPeiLib.c
new file mode 100755
index 000000000000..bb873f04e46d
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformPeiLib.c
@@ -0,0 +1,47 @@ 
+/** @file
+*
+*  Copyright (c) 2011-2012, 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 <PiPei.h>
+
+#include <Library/MemoryAllocationLib.h>
+#include <Library/ArmPlatformLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <libfdt.h>
+
+EFI_STATUS
+EFIAPI
+PlatformPeim (
+  VOID
+  )
+{
+  UINT64               Base;
+  VOID                *NewBase;
+  UINTN                FdtSize;
+
+  BuildFvHob (PcdGet32(PcdFvBaseAddress), PcdGet32(PcdFvSize));
+
+  Base = PcdGet64 (PcdDeviceTreeBaseAddress);
+  FdtSize = fdt_totalsize ((VOID *)(UINTN)Base);
+
+  NewBase = AllocatePages (EFI_SIZE_TO_PAGES (FdtSize));
+  ASSERT (NewBase != NULL);
+
+  CopyMem (NewBase, (VOID *)(UINTN)Base, FdtSize);
+  PcdSet64 (PcdDeviceTreeBaseAddress, (UINT64)NewBase);
+
+  return EFI_SUCCESS;
+}
diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformPeiLib.inf b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformPeiLib.inf
new file mode 100755
index 000000000000..b1e8bc986efc
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/PlatformPei/PlatformPeiLib.inf
@@ -0,0 +1,58 @@ 
+#/** @file
+#
+#  Copyright (c) 2011-2012, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = ArmPlatformPeiLib
+  FILE_GUID                      = 49d37060-70b5-11e0-aa2d-0002a5d5c51b
+  MODULE_TYPE                    = SEC
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PlatformPeiLib
+
+[Sources]
+  PlatformPeiLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+  DebugLib
+  HobLib
+  ArmPlatformLib
+  FdtLib
+
+[Ppis]
+  gEfiPeiMasterBootModePpiGuid                  # PPI ALWAYS_PRODUCED
+  gEfiPeiBootInRecoveryModePpiGuid              # PPI SOMETIMES_PRODUCED
+
+[FixedPcd]
+  gArmTokenSpaceGuid.PcdFdBaseAddress
+  gArmTokenSpaceGuid.PcdFdSize
+
+  gArmTokenSpaceGuid.PcdFvBaseAddress
+  gArmTokenSpaceGuid.PcdFvSize
+
+  gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize
+  gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize
+
+[Pcd]
+  gArmTokenSpaceGuid.PcdDeviceTreeBaseAddress
+
+[depex]
+  gEfiPeiMemoryDiscoveredPpiGuid
+
diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.c b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.c
new file mode 100644
index 000000000000..a420591a8e9c
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.c
@@ -0,0 +1,97 @@ 
+/** @file
+  Support ResetSystem Runtime call using PSCI hvc calls
+
+  Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+  Copyright (c) 2013, ARM Ltd. All rights reserved.<BR>
+  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 <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/EfiResetSystemLib.h>
+
+VOID
+ArmPsciSystemReset (
+  VOID
+  );
+
+VOID
+ArmPsciSystemOff (
+  VOID
+  );
+
+/**
+  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
+  )
+{
+  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
+    ArmPsciSystemReset ();
+    break;
+  case EfiResetShutdown:
+    // Send a PSCI 0.2 SYSTEM_OFF command
+    ArmPsciSystemOff ();
+    break;
+
+  default:
+    ASSERT (FALSE);
+    return EFI_UNSUPPORTED;
+  }
+
+  // We should never be here
+  DEBUG ((EFI_D_ERROR, "%a: PSCI Reset failed\n", __FUNCTION__));
+  CpuDeadLoop ();
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  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..ed25977ff349
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemLib.inf
@@ -0,0 +1,36 @@ 
+#/** @file
+# Reset System lib to make it easy to port new platforms
+#
+# Copyright (c) 2008, Apple Inc. All rights reserved.<BR>
+#
+#  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
+  ResetSystemPsci.S | GCC
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  MdePkg/MdePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+  IoLib
+  DebugLib
+  BaseLib
diff --git a/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemPsci.S b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemPsci.S
new file mode 100644
index 000000000000..988b0fdc41e4
--- /dev/null
+++ b/ArmPlatformPkg/AArch64VirtualizationPkg/Library/ResetSystemLib/ResetSystemPsci.S
@@ -0,0 +1,40 @@ 
+/** @file
+  Support ResetSystem Runtime call using PSCI hvc calls
+
+  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 <AsmMacroIoLibV8.h>
+#include <Base.h>
+#include <Library/ArmLib.h>
+#include <AutoGen.h>
+
+#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)
+
+.text
+.align 2
+
+GCC_ASM_EXPORT(ArmPsciSystemOff)
+GCC_ASM_EXPORT(ArmPsciSystemReset)
+
+ASM_PFX(ArmPsciSystemOff):
+  ldr    w0, =PSCI_0_2_FN_SYSTEM_OFF
+  hvc    #0
+  ret
+
+ASM_PFX(ArmPsciSystemReset):
+  ldr    w0, =PSCI_0_2_FN_SYSTEM_RESET
+  hvc    #0
+  ret