summaryrefslogtreecommitdiff
path: root/ArmVirtPkg/Library
diff options
context:
space:
mode:
authorOlivier Martin <olivier.martin@arm.com>2015-05-29 13:50:43 +0000
committeroliviermartin <oliviermartin@Edk2>2015-05-29 13:50:43 +0000
commit7fbd1eb2312d3dfab2ac8cdfcefc234c73d8aeeb (patch)
tree0062d16f930c05cb0fe7e7eececca5f8fb91b18e /ArmVirtPkg/Library
parent4c31caef17170dfd5bd7fe82b890078547750370 (diff)
downloadedk2-platforms-7fbd1eb2312d3dfab2ac8cdfcefc234c73d8aeeb.tar.xz
Renamed ArmPlatformPkg/ArmVirtualizationPkg into ArmVirtPkg
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Olivier Martin <olivier.martin@arm.com> Reviewed-by: Laszlo Ersek <lersek@redhat.com> Tested-by: Laszlo Ersek <lersek@redhat.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17537 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'ArmVirtPkg/Library')
-rw-r--r--ArmVirtPkg/Library/ArmVirtDxeHobLib/ArmVirtDxeHobLib.inf40
-rw-r--r--ArmVirtPkg/Library/ArmVirtDxeHobLib/HobLib.c577
-rw-r--r--ArmVirtPkg/Library/ArmVirtMemoryInitPeiLib/ArmVirtMemoryInitPeiLib.c101
-rw-r--r--ArmVirtPkg/Library/ArmVirtMemoryInitPeiLib/ArmVirtMemoryInitPeiLib.inf67
-rw-r--r--ArmVirtPkg/Library/ArmVirtPlatformLib/AARCH64/VirtHelper.S86
-rw-r--r--ArmVirtPkg/Library/ArmVirtPlatformLib/ARM/VirtHelper.S74
-rw-r--r--ArmVirtPkg/Library/ArmVirtPlatformLib/ARM/VirtHelper.asm79
-rw-r--r--ArmVirtPkg/Library/ArmVirtPlatformLib/ArmVirtPlatformLib.inf63
-rw-r--r--ArmVirtPkg/Library/ArmVirtPlatformLib/Virt.c155
-rw-r--r--ArmVirtPkg/Library/ArmVirtPlatformLib/VirtMem.c107
-rw-r--r--ArmVirtPkg/Library/ArmVirtPsciResetSystemLib/ArmVirtPsciResetSystemLib.c125
-rw-r--r--ArmVirtPkg/Library/ArmVirtPsciResetSystemLib/ArmVirtPsciResetSystemLib.inf42
-rw-r--r--ArmVirtPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/MemnodeParser.S237
-rw-r--r--ArmVirtPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/RelocatableVirtHelper.S167
-rw-r--r--ArmVirtPkg/Library/ArmXenRelocatablePlatformLib/ArmXenRelocatablePlatformLib.inf59
-rw-r--r--ArmVirtPkg/Library/ArmXenRelocatablePlatformLib/RelocatableVirt.c71
-rw-r--r--ArmVirtPkg/Library/ArmXenRelocatablePlatformLib/XenVirtMem.c83
-rw-r--r--ArmVirtPkg/Library/BaseCachingPciExpressLib/BaseCachingPciExpressLib.inf46
-rw-r--r--ArmVirtPkg/Library/BaseCachingPciExpressLib/PciExpressLib.c1429
-rw-r--r--ArmVirtPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.c185
-rw-r--r--ArmVirtPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.inf45
-rw-r--r--ArmVirtPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.c150
-rw-r--r--ArmVirtPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.inf48
-rw-r--r--ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c51
-rw-r--r--ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf30
-rw-r--r--ArmVirtPkg/Library/PlatformIntelBdsLib/IntelBdsPlatform.c477
-rw-r--r--ArmVirtPkg/Library/PlatformIntelBdsLib/IntelBdsPlatform.h55
-rw-r--r--ArmVirtPkg/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf74
-rw-r--r--ArmVirtPkg/Library/PlatformIntelBdsLib/QemuKernel.c1108
-rw-r--r--ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c102
-rw-r--r--ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.inf52
-rw-r--r--ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c358
-rw-r--r--ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf52
-rw-r--r--ArmVirtPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.c196
-rw-r--r--ArmVirtPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.inf38
35 files changed, 6629 insertions, 0 deletions
diff --git a/ArmVirtPkg/Library/ArmVirtDxeHobLib/ArmVirtDxeHobLib.inf b/ArmVirtPkg/Library/ArmVirtDxeHobLib/ArmVirtDxeHobLib.inf
new file mode 100644
index 0000000000..2a3df69d77
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmVirtDxeHobLib/ArmVirtDxeHobLib.inf
@@ -0,0 +1,40 @@
+## @file
+# Instance of HOB Library using HOB list from EFI Configuration Table, with
+# DebugLib dependency removed
+#
+# HOB Library implementation that retrieves the HOB List
+# from the System Configuration Table in the EFI System Table.
+#
+# Copyright (c) 2007 - 2014, Intel Corporation. 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.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmVirtDxeHobLib
+ FILE_GUID = 3CD90EEC-EBF3-425D-AAE8-B16215AC4F50
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = HobLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER SMM_CORE DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER
+ CONSTRUCTOR = HobLibConstructor
+
+[Sources]
+ HobLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+
+[Guids]
+ gEfiHobListGuid ## CONSUMES ## SystemTable
diff --git a/ArmVirtPkg/Library/ArmVirtDxeHobLib/HobLib.c b/ArmVirtPkg/Library/ArmVirtDxeHobLib/HobLib.c
new file mode 100644
index 0000000000..81196b207d
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmVirtDxeHobLib/HobLib.c
@@ -0,0 +1,577 @@
+/** @file
+ HOB Library implemenation for Dxe Phase with DebugLib dependency removed
+
+Copyright (c) 2006 - 2012, Intel Corporation. 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.
+
+**/
+
+#define ASSERT(Expression) \
+ do { \
+ if (!(Expression)) { \
+ CpuDeadLoop (); \
+ } \
+ } while (FALSE)
+
+#include <PiDxe.h>
+
+#include <Guid/HobList.h>
+
+#include <Library/HobLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+
+VOID *mHobList = NULL;
+
+/**
+ The constructor function caches the pointer to HOB list.
+
+ The constructor function gets the start address of HOB list from system configuration table.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The constructor successfully gets HobList.
+ @retval Other value The constructor can't get HobList.
+
+**/
+EFI_STATUS
+EFIAPI
+HobLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < SystemTable->NumberOfTableEntries; Index++) {
+ if (CompareGuid (&gEfiHobListGuid, &(SystemTable->ConfigurationTable[Index].VendorGuid))) {
+ mHobList = SystemTable->ConfigurationTable[Index].VendorTable;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Returns the pointer to the HOB list.
+
+ This function returns the pointer to first HOB in the list.
+ For PEI phase, the PEI service GetHobList() can be used to retrieve the pointer
+ to the HOB list. For the DXE phase, the HOB list pointer can be retrieved through
+ the EFI System Table by looking up theHOB list GUID in the System Configuration Table.
+ Since the System Configuration Table does not exist that the time the DXE Core is
+ launched, the DXE Core uses a global variable from the DXE Core Entry Point Library
+ to manage the pointer to the HOB list.
+
+ If the pointer to the HOB list is NULL, then ASSERT().
+
+ @return The pointer to the HOB list.
+
+**/
+VOID *
+EFIAPI
+GetHobList (
+ VOID
+ )
+{
+ ASSERT (mHobList != NULL);
+ return mHobList;
+}
+
+/**
+ Returns the next instance of a HOB type from the starting HOB.
+
+ This function searches the first instance of a HOB type from the starting HOB pointer.
+ If there does not exist such HOB type from the starting HOB pointer, it will return NULL.
+ In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer
+ unconditionally: it returns HobStart back if HobStart itself meets the requirement;
+ caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart.
+
+ If HobStart is NULL, then ASSERT().
+
+ @param Type The HOB type to return.
+ @param HobStart The starting HOB pointer to search from.
+
+ @return The next instance of a HOB type from the starting HOB.
+
+**/
+VOID *
+EFIAPI
+GetNextHob (
+ IN UINT16 Type,
+ IN CONST VOID *HobStart
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+
+ ASSERT (HobStart != NULL);
+
+ Hob.Raw = (UINT8 *) HobStart;
+ //
+ // Parse the HOB list until end of list or matching type is found.
+ //
+ while (!END_OF_HOB_LIST (Hob)) {
+ if (Hob.Header->HobType == Type) {
+ return Hob.Raw;
+ }
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ }
+ return NULL;
+}
+
+/**
+ Returns the first instance of a HOB type among the whole HOB list.
+
+ This function searches the first instance of a HOB type among the whole HOB list.
+ If there does not exist such HOB type in the HOB list, it will return NULL.
+
+ If the pointer to the HOB list is NULL, then ASSERT().
+
+ @param Type The HOB type to return.
+
+ @return The next instance of a HOB type from the starting HOB.
+
+**/
+VOID *
+EFIAPI
+GetFirstHob (
+ IN UINT16 Type
+ )
+{
+ VOID *HobList;
+
+ HobList = GetHobList ();
+ return GetNextHob (Type, HobList);
+}
+
+/**
+ Returns the next instance of the matched GUID HOB from the starting HOB.
+
+ This function searches the first instance of a HOB from the starting HOB pointer.
+ Such HOB should satisfy two conditions:
+ its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid.
+ If there does not exist such HOB from the starting HOB pointer, it will return NULL.
+ Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE ()
+ to extract the data section and its size information, respectively.
+ In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer
+ unconditionally: it returns HobStart back if HobStart itself meets the requirement;
+ caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart.
+
+ If Guid is NULL, then ASSERT().
+ If HobStart is NULL, then ASSERT().
+
+ @param Guid The GUID to match with in the HOB list.
+ @param HobStart A pointer to a Guid.
+
+ @return The next instance of the matched GUID HOB from the starting HOB.
+
+**/
+VOID *
+EFIAPI
+GetNextGuidHob (
+ IN CONST EFI_GUID *Guid,
+ IN CONST VOID *HobStart
+ )
+{
+ EFI_PEI_HOB_POINTERS GuidHob;
+
+ GuidHob.Raw = (UINT8 *) HobStart;
+ while ((GuidHob.Raw = GetNextHob (EFI_HOB_TYPE_GUID_EXTENSION, GuidHob.Raw)) != NULL) {
+ if (CompareGuid (Guid, &GuidHob.Guid->Name)) {
+ break;
+ }
+ GuidHob.Raw = GET_NEXT_HOB (GuidHob);
+ }
+ return GuidHob.Raw;
+}
+
+/**
+ Returns the first instance of the matched GUID HOB among the whole HOB list.
+
+ This function searches the first instance of a HOB among the whole HOB list.
+ Such HOB should satisfy two conditions:
+ its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid.
+ If there does not exist such HOB from the starting HOB pointer, it will return NULL.
+ Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE ()
+ to extract the data section and its size information, respectively.
+
+ If the pointer to the HOB list is NULL, then ASSERT().
+ If Guid is NULL, then ASSERT().
+
+ @param Guid The GUID to match with in the HOB list.
+
+ @return The first instance of the matched GUID HOB among the whole HOB list.
+
+**/
+VOID *
+EFIAPI
+GetFirstGuidHob (
+ IN CONST EFI_GUID *Guid
+ )
+{
+ VOID *HobList;
+
+ HobList = GetHobList ();
+ return GetNextGuidHob (Guid, HobList);
+}
+
+/**
+ Get the system boot mode from the HOB list.
+
+ This function returns the system boot mode information from the
+ PHIT HOB in HOB list.
+
+ If the pointer to the HOB list is NULL, then ASSERT().
+
+ @param VOID
+
+ @return The Boot Mode.
+
+**/
+EFI_BOOT_MODE
+EFIAPI
+GetBootModeHob (
+ VOID
+ )
+{
+ EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob;
+
+ HandOffHob = (EFI_HOB_HANDOFF_INFO_TABLE *) GetHobList ();
+
+ return HandOffHob->BootMode;
+}
+
+/**
+ Builds a HOB for a loaded PE32 module.
+
+ This function builds a HOB for a loaded PE32 module.
+ It can only be invoked during PEI phase;
+ for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
+
+ If ModuleName is NULL, then ASSERT().
+ If there is no additional space for HOB creation, then ASSERT().
+
+ @param ModuleName The GUID File Name of the module.
+ @param MemoryAllocationModule The 64 bit physical address of the module.
+ @param ModuleLength The length of the module in bytes.
+ @param EntryPoint The 64 bit physical address of the module entry point.
+
+**/
+VOID
+EFIAPI
+BuildModuleHob (
+ IN CONST EFI_GUID *ModuleName,
+ IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule,
+ IN UINT64 ModuleLength,
+ IN EFI_PHYSICAL_ADDRESS EntryPoint
+ )
+{
+ //
+ // PEI HOB is read only for DXE phase
+ //
+ ASSERT (FALSE);
+}
+
+/**
+ Builds a HOB that describes a chunk of system memory.
+
+ This function builds a HOB that describes a chunk of system memory.
+ It can only be invoked during PEI phase;
+ for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
+
+ If there is no additional space for HOB creation, then ASSERT().
+
+ @param ResourceType The type of resource described by this HOB.
+ @param ResourceAttribute The resource attributes of the memory described by this HOB.
+ @param PhysicalStart The 64 bit physical address of memory described by this HOB.
+ @param NumberOfBytes The length of the memory described by this HOB in bytes.
+
+**/
+VOID
+EFIAPI
+BuildResourceDescriptorHob (
+ IN EFI_RESOURCE_TYPE ResourceType,
+ IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute,
+ IN EFI_PHYSICAL_ADDRESS PhysicalStart,
+ IN UINT64 NumberOfBytes
+ )
+{
+ //
+ // PEI HOB is read only for DXE phase
+ //
+ ASSERT (FALSE);
+}
+
+/**
+ Builds a customized HOB tagged with a GUID for identification and returns
+ the start address of GUID HOB data.
+
+ This function builds a customized HOB tagged with a GUID for identification
+ and returns the start address of GUID HOB data so that caller can fill the customized data.
+ The HOB Header and Name field is already stripped.
+ It can only be invoked during PEI phase;
+ for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
+
+ If Guid is NULL, then ASSERT().
+ If there is no additional space for HOB creation, then ASSERT().
+ If DataLength > (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT().
+ HobLength is UINT16 and multiples of 8 bytes, so the max HobLength is 0xFFF8.
+
+ @param Guid The GUID to tag the customized HOB.
+ @param DataLength The size of the data payload for the GUID HOB.
+
+ @retval NULL The GUID HOB could not be allocated.
+ @retval others The start address of GUID HOB data.
+
+**/
+VOID *
+EFIAPI
+BuildGuidHob (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN DataLength
+ )
+{
+ //
+ // PEI HOB is read only for DXE phase
+ //
+ ASSERT (FALSE);
+ return NULL;
+}
+
+/**
+ Builds a customized HOB tagged with a GUID for identification, copies the input data to the HOB
+ data field, and returns the start address of the GUID HOB data.
+
+ This function builds a customized HOB tagged with a GUID for identification and copies the input
+ data to the HOB data field and returns the start address of the GUID HOB data. It can only be
+ invoked during PEI phase; for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
+ The HOB Header and Name field is already stripped.
+ It can only be invoked during PEI phase;
+ for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
+
+ If Guid is NULL, then ASSERT().
+ If Data is NULL and DataLength > 0, then ASSERT().
+ If there is no additional space for HOB creation, then ASSERT().
+ If DataLength > (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT().
+ HobLength is UINT16 and multiples of 8 bytes, so the max HobLength is 0xFFF8.
+
+ @param Guid The GUID to tag the customized HOB.
+ @param Data The data to be copied into the data field of the GUID HOB.
+ @param DataLength The size of the data payload for the GUID HOB.
+
+ @retval NULL The GUID HOB could not be allocated.
+ @retval others The start address of GUID HOB data.
+
+**/
+VOID *
+EFIAPI
+BuildGuidDataHob (
+ IN CONST EFI_GUID *Guid,
+ IN VOID *Data,
+ IN UINTN DataLength
+ )
+{
+ //
+ // PEI HOB is read only for DXE phase
+ //
+ ASSERT (FALSE);
+ return NULL;
+}
+
+/**
+ Builds a Firmware Volume HOB.
+
+ This function builds a Firmware Volume HOB.
+ It can only be invoked during PEI phase;
+ for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
+
+ If there is no additional space for HOB creation, then ASSERT().
+
+ @param BaseAddress The base address of the Firmware Volume.
+ @param Length The size of the Firmware Volume in bytes.
+
+**/
+VOID
+EFIAPI
+BuildFvHob (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+{
+ //
+ // PEI HOB is read only for DXE phase
+ //
+ ASSERT (FALSE);
+}
+
+/**
+ Builds a EFI_HOB_TYPE_FV2 HOB.
+
+ This function builds a EFI_HOB_TYPE_FV2 HOB.
+ It can only be invoked during PEI phase;
+ for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
+
+ If there is no additional space for HOB creation, then ASSERT().
+
+ @param BaseAddress The base address of the Firmware Volume.
+ @param Length The size of the Firmware Volume in bytes.
+ @param FvName The name of the Firmware Volume.
+ @param FileName The name of the file.
+
+**/
+VOID
+EFIAPI
+BuildFv2Hob (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN CONST EFI_GUID *FvName,
+ IN CONST EFI_GUID *FileName
+ )
+{
+ ASSERT (FALSE);
+}
+
+
+/**
+ Builds a Capsule Volume HOB.
+
+ This function builds a Capsule Volume HOB.
+ It can only be invoked during PEI phase;
+ for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
+
+ If the platform does not support Capsule Volume HOBs, then ASSERT().
+ If there is no additional space for HOB creation, then ASSERT().
+
+ @param BaseAddress The base address of the Capsule Volume.
+ @param Length The size of the Capsule Volume in bytes.
+
+**/
+VOID
+EFIAPI
+BuildCvHob (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+{
+ //
+ // PEI HOB is read only for DXE phase
+ //
+ ASSERT (FALSE);
+}
+
+/**
+ Builds a HOB for the CPU.
+
+ This function builds a HOB for the CPU.
+ It can only be invoked during PEI phase;
+ for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
+
+ If there is no additional space for HOB creation, then ASSERT().
+
+ @param SizeOfMemorySpace The maximum physical memory addressability of the processor.
+ @param SizeOfIoSpace The maximum physical I/O addressability of the processor.
+
+**/
+VOID
+EFIAPI
+BuildCpuHob (
+ IN UINT8 SizeOfMemorySpace,
+ IN UINT8 SizeOfIoSpace
+ )
+{
+ //
+ // PEI HOB is read only for DXE phase
+ //
+ ASSERT (FALSE);
+}
+
+/**
+ Builds a HOB for the Stack.
+
+ This function builds a HOB for the stack.
+ It can only be invoked during PEI phase;
+ for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
+
+ If there is no additional space for HOB creation, then ASSERT().
+
+ @param BaseAddress The 64 bit physical address of the Stack.
+ @param Length The length of the stack in bytes.
+
+**/
+VOID
+EFIAPI
+BuildStackHob (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+{
+ //
+ // PEI HOB is read only for DXE phase
+ //
+ ASSERT (FALSE);
+}
+
+/**
+ Builds a HOB for the BSP store.
+
+ This function builds a HOB for BSP store.
+ It can only be invoked during PEI phase;
+ for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
+
+ If there is no additional space for HOB creation, then ASSERT().
+
+ @param BaseAddress The 64 bit physical address of the BSP.
+ @param Length The length of the BSP store in bytes.
+ @param MemoryType Type of memory allocated by this HOB.
+
+**/
+VOID
+EFIAPI
+BuildBspStoreHob (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN EFI_MEMORY_TYPE MemoryType
+ )
+{
+ //
+ // PEI HOB is read only for DXE phase
+ //
+ ASSERT (FALSE);
+}
+
+/**
+ Builds a HOB for the memory allocation.
+
+ This function builds a HOB for the memory allocation.
+ It can only be invoked during PEI phase;
+ for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
+
+ If there is no additional space for HOB creation, then ASSERT().
+
+ @param BaseAddress The 64 bit physical address of the memory.
+ @param Length The length of the memory allocation in bytes.
+ @param MemoryType Type of memory allocated by this HOB.
+
+**/
+VOID
+EFIAPI
+BuildMemoryAllocationHob (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN EFI_MEMORY_TYPE MemoryType
+ )
+{
+ //
+ // PEI HOB is read only for DXE phase
+ //
+ ASSERT (FALSE);
+}
diff --git a/ArmVirtPkg/Library/ArmVirtMemoryInitPeiLib/ArmVirtMemoryInitPeiLib.c b/ArmVirtPkg/Library/ArmVirtMemoryInitPeiLib/ArmVirtMemoryInitPeiLib.c
new file mode 100644
index 0000000000..8ce63b4596
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmVirtMemoryInitPeiLib/ArmVirtMemoryInitPeiLib.c
@@ -0,0 +1,101 @@
+/** @file
+*
+* Copyright (c) 2011-2014, ARM Limited. All rights reserved.
+* Copyright (c) 2014, Linaro Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <PiPei.h>
+
+#include <Library/ArmPlatformLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/CacheMaintenanceLib.h>
+
+VOID
+BuildMemoryTypeInformationHob (
+ VOID
+ );
+
+VOID
+InitMmu (
+ VOID
+ )
+{
+ ARM_MEMORY_REGION_DESCRIPTOR *MemoryTable;
+ VOID *TranslationTableBase;
+ UINTN TranslationTableSize;
+ RETURN_STATUS Status;
+
+ // Get Virtual Memory Map from the Platform Library
+ ArmPlatformGetVirtualMemoryMap (&MemoryTable);
+
+ //Note: Because we called PeiServicesInstallPeiMemory() before to call InitMmu() the MMU Page Table resides in
+ // DRAM (even at the top of DRAM as it is the first permanent memory allocation)
+ Status = ArmConfigureMmu (MemoryTable, &TranslationTableBase, &TranslationTableSize);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Error: Failed to enable MMU\n"));
+ }
+}
+
+EFI_STATUS
+EFIAPI
+MemoryPeim (
+ IN EFI_PHYSICAL_ADDRESS UefiMemoryBase,
+ IN UINT64 UefiMemorySize
+ )
+{
+ EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttributes;
+
+ // Ensure PcdSystemMemorySize has been set
+ ASSERT (PcdGet64 (PcdSystemMemorySize) != 0);
+
+ //
+ // Now, the permanent memory has been installed, we can call AllocatePages()
+ //
+ ResourceAttributes = (
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_TESTED
+ );
+
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY,
+ ResourceAttributes,
+ PcdGet64 (PcdSystemMemoryBase),
+ PcdGet64 (PcdSystemMemorySize)
+ );
+
+ //
+ // When running under virtualization, the PI/UEFI memory region may be
+ // clean but not invalidated in system caches or in lower level caches
+ // on other CPUs. So invalidate the region by virtual address, to ensure
+ // that the contents we put there with the caches and MMU off will still
+ // be visible after turning them on.
+ //
+ InvalidateDataCacheRange ((VOID*)(UINTN)UefiMemoryBase, UefiMemorySize);
+
+ // Build Memory Allocation Hob
+ InitMmu ();
+
+ if (FeaturePcdGet (PcdPrePiProduceMemoryTypeInformationHob)) {
+ // Optional feature that helps prevent EFI memory map fragmentation.
+ BuildMemoryTypeInformationHob ();
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/ArmVirtPkg/Library/ArmVirtMemoryInitPeiLib/ArmVirtMemoryInitPeiLib.inf b/ArmVirtPkg/Library/ArmVirtMemoryInitPeiLib/ArmVirtMemoryInitPeiLib.inf
new file mode 100644
index 0000000000..9fba16f90f
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmVirtMemoryInitPeiLib/ArmVirtMemoryInitPeiLib.inf
@@ -0,0 +1,67 @@
+#/** @file
+#
+# Copyright (c) 2011-2014, 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.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmVirtMemoryInitPeiLib
+ FILE_GUID = 021b6156-3cc8-4e99-85ee-13d8a871edf2
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = MemoryInitPeiLib
+
+[Sources]
+ ArmVirtMemoryInitPeiLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ HobLib
+ ArmLib
+ ArmPlatformLib
+ CacheMaintenanceLib
+
+[Guids]
+ gEfiMemoryTypeInformationGuid
+
+[FeaturePcd]
+ gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdFdSize
+
+ gArmPlatformTokenSpaceGuid.PcdSystemMemoryUefiRegionSize
+
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData
+
+[Pcd]
+ gArmTokenSpaceGuid.PcdSystemMemoryBase
+ gArmTokenSpaceGuid.PcdSystemMemorySize
+ gArmTokenSpaceGuid.PcdFdBaseAddress
+
+[Depex]
+ TRUE
diff --git a/ArmVirtPkg/Library/ArmVirtPlatformLib/AARCH64/VirtHelper.S b/ArmVirtPkg/Library/ArmVirtPlatformLib/AARCH64/VirtHelper.S
new file mode 100644
index 0000000000..14200fc17b
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmVirtPlatformLib/AARCH64/VirtHelper.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(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
+
+//UINTN
+//ArmPlatformIsPrimaryCore (
+// IN UINTN MpId
+// );
+ASM_PFX(ArmPlatformIsPrimaryCore):
+ mov x0, #1
+ ret
+
+//UINTN
+//ArmPlatformGetCorePosition (
+// IN UINTN MpId
+// );
+// With this function: CorePos = (ClusterId * 4) + CoreId
+ASM_PFX(ArmPlatformGetCorePosition):
+ and x1, x0, #ARM_CORE_MASK
+ and x0, x0, #ARM_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+
+//EFI_PHYSICAL_ADDRESS
+//GetPhysAddrTop (
+// VOID
+// );
+ASM_PFX(ArmGetPhysAddrTop):
+ mrs x0, id_aa64mmfr0_el1
+ adr x1, .LPARanges
+ and x0, x0, #7
+ ldrb w1, [x1, x0]
+ mov x0, #1
+ lsl x0, x0, x1
+ ret
+
+//
+// Bits 0..2 of the AA64MFR0_EL1 system register encode the size of the
+// physical address space support on this CPU:
+// 0 == 32 bits, 1 == 36 bits, etc etc
+// 6 and 7 are reserved
+//
+.LPARanges:
+ .byte 32, 36, 40, 42, 44, 48, -1, -1
+
+ASM_FUNCTION_REMOVE_IF_UNREFERENCED
diff --git a/ArmVirtPkg/Library/ArmVirtPlatformLib/ARM/VirtHelper.S b/ArmVirtPkg/Library/ArmVirtPlatformLib/ARM/VirtHelper.S
new file mode 100644
index 0000000000..255f995987
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmVirtPlatformLib/ARM/VirtHelper.S
@@ -0,0 +1,74 @@
+#
+# 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 <AsmMacroIoLib.h>
+#include <Base.h>
+#include <Library/ArmLib.h>
+#include <Library/PcdLib.h>
+#include <AutoGen.h>
+
+.text
+.align 2
+
+GCC_ASM_EXPORT(ArmPlatformPeiBootAction)
+GCC_ASM_EXPORT(ArmPlatformIsPrimaryCore)
+GCC_ASM_EXPORT(ArmPlatformGetPrimaryCoreMpId)
+GCC_ASM_EXPORT(ArmPlatformGetCorePosition)
+GCC_ASM_EXPORT(ArmGetPhysAddrTop)
+
+GCC_ASM_IMPORT(_gPcd_FixedAtBuild_PcdArmPrimaryCore)
+GCC_ASM_IMPORT(_gPcd_FixedAtBuild_PcdArmPrimaryCoreMask)
+GCC_ASM_IMPORT(_gPcd_FixedAtBuild_PcdCoreCount)
+
+ASM_PFX(ArmPlatformPeiBootAction):
+ bx lr
+
+//UINTN
+//ArmPlatformGetPrimaryCoreMpId (
+// VOID
+// );
+ASM_PFX(ArmPlatformGetPrimaryCoreMpId):
+ LoadConstantToReg (_gPcd_FixedAtBuild_PcdArmPrimaryCore, r0)
+ ldr r0, [r0]
+ bx lr
+
+//UINTN
+//ArmPlatformIsPrimaryCore (
+// IN UINTN MpId
+// );
+ASM_PFX(ArmPlatformIsPrimaryCore):
+ mov r0, #1
+ bx lr
+
+//UINTN
+//ArmPlatformGetCorePosition (
+// IN UINTN MpId
+// );
+// With this function: CorePos = (ClusterId * 4) + CoreId
+ASM_PFX(ArmPlatformGetCorePosition):
+ and r1, r0, #ARM_CORE_MASK
+ and r0, r0, #ARM_CLUSTER_MASK
+ add r0, r1, r0, LSR #6
+ bx lr
+
+//EFI_PHYSICAL_ADDRESS
+//GetPhysAddrTop (
+// VOID
+// );
+ASM_PFX(ArmGetPhysAddrTop):
+ mov r0, #0x00000000
+ mov r1, #0x10000
+ bx lr
+
+ASM_FUNCTION_REMOVE_IF_UNREFERENCED
diff --git a/ArmVirtPkg/Library/ArmVirtPlatformLib/ARM/VirtHelper.asm b/ArmVirtPkg/Library/ArmVirtPlatformLib/ARM/VirtHelper.asm
new file mode 100644
index 0000000000..7882e63217
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmVirtPlatformLib/ARM/VirtHelper.asm
@@ -0,0 +1,79 @@
+//
+// Copyright (c) 2011-2014, ARM Limited. All rights reserved.
+// Copyright (c) 2014, Linaro Limited. All rights reserved.
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+
+#include <AsmMacroIoLib.h>
+#include <Base.h>
+#include <Library/ArmLib.h>
+#include <Library/PcdLib.h>
+#include <AutoGen.h>
+
+ INCLUDE AsmMacroIoLib.inc
+
+ EXPORT ArmPlatformPeiBootAction
+ EXPORT ArmPlatformIsPrimaryCore
+ EXPORT ArmPlatformGetPrimaryCoreMpId
+ EXPORT ArmPlatformGetCorePosition
+ EXPORT ArmGetPhysAddrTop
+
+ IMPORT _gPcd_FixedAtBuild_PcdArmPrimaryCore
+ IMPORT _gPcd_FixedAtBuild_PcdArmPrimaryCoreMask
+ IMPORT _gPcd_FixedAtBuild_PcdCoreCount
+
+ AREA VirtHelper, CODE, READONLY
+
+ArmPlatformPeiBootAction FUNCTION
+ bx lr
+ ENDFUNC
+
+//UINTN
+//ArmPlatformGetPrimaryCoreMpId (
+// VOID
+// );
+ArmPlatformGetPrimaryCoreMpId FUNCTION
+ LoadConstantToReg (_gPcd_FixedAtBuild_PcdArmPrimaryCore, r0)
+ ldr r0, [r0]
+ bx lr
+ ENDFUNC
+
+//UINTN
+//ArmPlatformIsPrimaryCore (
+// IN UINTN MpId
+// );
+ArmPlatformIsPrimaryCore FUNCTION
+ mov r0, #1
+ bx lr
+ ENDFUNC
+
+//UINTN
+//ArmPlatformGetCorePosition (
+// IN UINTN MpId
+// );
+// With this function: CorePos = (ClusterId * 4) + CoreId
+ArmPlatformGetCorePosition FUNCTION
+ and r1, r0, #ARM_CORE_MASK
+ and r0, r0, #ARM_CLUSTER_MASK
+ add r0, r1, r0, LSR #6
+ bx lr
+ ENDFUNC
+
+//EFI_PHYSICAL_ADDRESS
+//GetPhysAddrTop (
+// VOID
+// );
+ArmGetPhysAddrTop FUNCTION
+ mov r0, #0x00000000
+ mov r1, #0x10000
+ bx lr
+ ENDFUNC
+
+ END
diff --git a/ArmVirtPkg/Library/ArmVirtPlatformLib/ArmVirtPlatformLib.inf b/ArmVirtPkg/Library/ArmVirtPlatformLib/ArmVirtPlatformLib.inf
new file mode 100644
index 0000000000..22ee3625c3
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmVirtPlatformLib/ArmVirtPlatformLib.inf
@@ -0,0 +1,63 @@
+#/* @file
+# Copyright (c) 2011-2014, ARM Limited. All rights reserved.
+# Copyright (c) 2014, Linaro Limited. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmVirtPlatformLib
+ FILE_GUID = 00214cc1-06d1-45fe-9700-dca5726ad7bf
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmPlatformLib|SEC PEIM
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ ArmVirtPkg/ArmVirtPkg.dec
+
+[LibraryClasses]
+ IoLib
+ MemoryAllocationLib
+ ArmLib
+ PrintLib
+ FdtLib
+
+[Sources.common]
+ Virt.c
+ VirtMem.c
+
+[Sources.AARCH64]
+ AARCH64/VirtHelper.S
+
+[Sources.ARM]
+ ARM/VirtHelper.S | GCC
+ ARM/VirtHelper.asm | RVCT
+
+[FeaturePcd]
+ gEmbeddedTokenSpaceGuid.PcdCacheEnable
+ gArmPlatformTokenSpaceGuid.PcdSystemMemoryInitializeInSec
+
+[Pcd]
+ gArmTokenSpaceGuid.PcdSystemMemorySize
+
+[FixedPcd]
+ gArmVirtTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress
+ gArmPlatformTokenSpaceGuid.PcdCoreCount
+ gArmTokenSpaceGuid.PcdSystemMemoryBase
+ gArmTokenSpaceGuid.PcdArmPrimaryCoreMask
+ gArmTokenSpaceGuid.PcdArmPrimaryCore
+ gArmTokenSpaceGuid.PcdFdBaseAddress
+ gArmTokenSpaceGuid.PcdFdSize
diff --git a/ArmVirtPkg/Library/ArmVirtPlatformLib/Virt.c b/ArmVirtPkg/Library/ArmVirtPlatformLib/Virt.c
new file mode 100644
index 0000000000..17f2686975
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmVirtPlatformLib/Virt.c
@@ -0,0 +1,155 @@
+/** @file
+*
+* Copyright (c) 2011-2013, ARM Limited. All rights reserved.
+* Copyright (c) 2014, Linaro Limited. All rights reserved.
+* Copyright (c) 2014, Red Hat, Inc.
+*
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Library/IoLib.h>
+#include <Library/ArmPlatformLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <ArmPlatform.h>
+#include <libfdt.h>
+#include <Pi/PiBootMode.h>
+#include <Uefi/UefiBaseType.h>
+#include <Uefi/UefiMultiPhase.h>
+
+/**
+ Return the current Boot Mode
+
+ This function returns the boot reason on the platform
+
+ @return Return the current Boot Mode of the platform
+
+**/
+EFI_BOOT_MODE
+ArmPlatformGetBootMode (
+ VOID
+ )
+{
+ return BOOT_WITH_FULL_CONFIGURATION;
+}
+
+/**
+ This function is called by PrePeiCore, in the SEC phase.
+**/
+RETURN_STATUS
+ArmPlatformInitialize (
+ IN UINTN MpId
+ )
+{
+ //
+ // We are relying on ArmPlatformInitializeSystemMemory () being called from
+ // InitializeMemory (), which only occurs if the following feature is disabled
+ //
+ ASSERT (!FeaturePcdGet (PcdSystemMemoryInitializeInSec));
+ return RETURN_SUCCESS;
+}
+
+/**
+ Initialize the system (or sometimes called permanent) memory
+
+ This memory is generally represented by the DRAM.
+
+ This function is called from InitializeMemory() in MemoryInitPeim, in the PEI
+ phase.
+**/
+VOID
+ArmPlatformInitializeSystemMemory (
+ VOID
+ )
+{
+ VOID *DeviceTreeBase;
+ INT32 Node, Prev;
+ UINT64 NewBase;
+ UINT64 NewSize;
+ CONST CHAR8 *Type;
+ INT32 Len;
+ CONST UINT64 *RegProp;
+
+ NewBase = 0;
+ NewSize = 0;
+
+ DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
+ ASSERT (DeviceTreeBase != NULL);
+
+ //
+ // Make sure we have a valid device tree blob
+ //
+ ASSERT (fdt_check_header (DeviceTreeBase) == 0);
+
+ //
+ // Look for a memory node
+ //
+ for (Prev = 0;; Prev = Node) {
+ Node = fdt_next_node (DeviceTreeBase, Prev, NULL);
+ if (Node < 0) {
+ break;
+ }
+
+ //
+ // Check for memory node
+ //
+ Type = fdt_getprop (DeviceTreeBase, Node, "device_type", &Len);
+ if (Type && AsciiStrnCmp (Type, "memory", Len) == 0) {
+ //
+ // Get the 'reg' property of this node. For now, we will assume
+ // two 8 byte quantities for base and size, respectively.
+ //
+ RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);
+ if (RegProp != 0 && Len == (2 * sizeof (UINT64))) {
+
+ NewBase = fdt64_to_cpu (ReadUnaligned64 (RegProp));
+ NewSize = fdt64_to_cpu (ReadUnaligned64 (RegProp + 1));
+
+ //
+ // Make sure the start of DRAM matches our expectation
+ //
+ ASSERT (FixedPcdGet64 (PcdSystemMemoryBase) == NewBase);
+ PcdSet64 (PcdSystemMemorySize, NewSize);
+
+ DEBUG ((EFI_D_INFO, "%a: System RAM @ 0x%lx - 0x%lx\n",
+ __FUNCTION__, NewBase, NewBase + NewSize - 1));
+ } else {
+ DEBUG ((EFI_D_ERROR, "%a: Failed to parse FDT memory node\n",
+ __FUNCTION__));
+ }
+ break;
+ }
+ }
+
+ //
+ // We need to make sure that the machine we are running on has at least
+ // 128 MB of memory configured, and is currently executing this binary from
+ // NOR flash. This prevents a device tree image in DRAM from getting
+ // clobbered when our caller installs permanent PEI RAM, before we have a
+ // chance of marking its location as reserved or copy it to a freshly
+ // allocated block in the permanent PEI RAM in the platform PEIM.
+ //
+ ASSERT (NewSize >= SIZE_128MB);
+ ASSERT (
+ (((UINT64)PcdGet64 (PcdFdBaseAddress) +
+ (UINT64)PcdGet32 (PcdFdSize)) <= NewBase) ||
+ ((UINT64)PcdGet64 (PcdFdBaseAddress) >= (NewBase + NewSize)));
+}
+
+VOID
+ArmPlatformGetPlatformPpiList (
+ OUT UINTN *PpiListSize,
+ OUT EFI_PEI_PPI_DESCRIPTOR **PpiList
+ )
+{
+ *PpiListSize = 0;
+ *PpiList = NULL;
+}
diff --git a/ArmVirtPkg/Library/ArmVirtPlatformLib/VirtMem.c b/ArmVirtPkg/Library/ArmVirtPlatformLib/VirtMem.c
new file mode 100644
index 0000000000..d5d288fb1b
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmVirtPlatformLib/VirtMem.c
@@ -0,0 +1,107 @@
+/** @file
+*
+* Copyright (c) 2014, Linaro Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Library/ArmPlatformLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/ArmPlatformGlobalVariableLib.h>
+#include <ArmPlatform.h>
+
+// Number of Virtual Memory Map Descriptors
+#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
+ ZeroMem (&VirtualMemoryTable[3], sizeof (ARM_MEMORY_REGION_DESCRIPTOR));
+
+ *VirtualMemoryMap = VirtualMemoryTable;
+}
diff --git a/ArmVirtPkg/Library/ArmVirtPsciResetSystemLib/ArmVirtPsciResetSystemLib.c b/ArmVirtPkg/Library/ArmVirtPsciResetSystemLib/ArmVirtPsciResetSystemLib.c
new file mode 100644
index 0000000000..88332f56fd
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmVirtPsciResetSystemLib/ArmVirtPsciResetSystemLib.c
@@ -0,0 +1,125 @@
+/** @file
+ Support ResetSystem Runtime call using PSCI calls
+
+ Note: A similar library is implemented in
+ ArmPkg/Library/ArmPsciResetSystemLib. Similar issues might
+ exist in this implementation too.
+
+ 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>
+#include <Library/ArmSmcLib.h>
+#include <Library/ArmHvcLib.h>
+
+#include <IndustryStandard/ArmStdSmc.h>
+
+STATIC UINT32 mArmPsciMethod;
+
+RETURN_STATUS
+EFIAPI
+ArmPsciResetSystemLibConstructor (
+ VOID
+ )
+{
+ mArmPsciMethod = PcdGet32 (PcdArmPsciMethod);
+ return RETURN_SUCCESS;
+}
+
+/**
+ 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
+ )
+{
+ ARM_SMC_ARGS ArmSmcArgs;
+ ARM_HVC_ARGS ArmHvcArgs;
+
+ 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
+ ArmSmcArgs.Arg0 = ARM_SMC_ID_PSCI_SYSTEM_RESET;
+ ArmHvcArgs.Arg0 = ARM_SMC_ID_PSCI_SYSTEM_RESET;
+ break;
+ case EfiResetShutdown:
+ // Send a PSCI 0.2 SYSTEM_OFF command
+ ArmSmcArgs.Arg0 = ARM_SMC_ID_PSCI_SYSTEM_OFF;
+ ArmHvcArgs.Arg0 = ARM_SMC_ID_PSCI_SYSTEM_OFF;
+ break;
+ default:
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ switch (mArmPsciMethod) {
+ case 1:
+ ArmCallHvc (&ArmHvcArgs);
+ break;
+
+ case 2:
+ ArmCallSmc (&ArmSmcArgs);
+ break;
+
+ default:
+ DEBUG ((EFI_D_ERROR, "%a: no PSCI method defined\n", __FUNCTION__));
+ 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/ArmVirtPkg/Library/ArmVirtPsciResetSystemLib/ArmVirtPsciResetSystemLib.inf b/ArmVirtPkg/Library/ArmVirtPsciResetSystemLib/ArmVirtPsciResetSystemLib.inf
new file mode 100644
index 0000000000..86d6104ca2
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmVirtPsciResetSystemLib/ArmVirtPsciResetSystemLib.inf
@@ -0,0 +1,42 @@
+#/** @file
+# Reset System lib using PSCI hypervisor or secure monitor calls
+#
+# Copyright (c) 2008, Apple Inc. 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.
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmVirtPsciResetSystemLib
+ FILE_GUID = c81d76ed-66fa-44a3-ac4a-f163120187a9
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = EfiResetSystemLib
+ CONSTRUCTOR = ArmPsciResetSystemLibConstructor
+
+[Sources]
+ ArmVirtPsciResetSystemLib.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ ArmVirtPkg/ArmVirtPkg.dec
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ BaseLib
+ ArmSmcLib
+ ArmHvcLib
+
+[Pcd]
+ gArmVirtTokenSpaceGuid.PcdArmPsciMethod
diff --git a/ArmVirtPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/MemnodeParser.S b/ArmVirtPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/MemnodeParser.S
new file mode 100644
index 0000000000..2bdaa3c951
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/MemnodeParser.S
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2014, Linaro Ltd. All rights reserved.
+ *
+ * This program and the accompanying materials
+ * are licensed and made available under the terms and conditions of the BSD License
+ * which accompanies this distribution. The full text of the license may be found at
+ * http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ */
+
+/*
+ * Theory of operation
+ * -------------------
+ *
+ * This code parses a Flattened Device Tree binary (DTB) to find the base of
+ * system RAM. It is written in assembly so that it can be executed before a
+ * stack has been set up.
+ *
+ * To find the base of system RAM, we have to traverse the FDT to find a memory
+ * node. In the context of this implementation, the first node that has a
+ * device_type property with the value 'memory' and a 'reg' property is
+ * acceptable, and the name of the node (memory[@xxx]) is ignored, as are any
+ * other nodes that match the above constraints.
+ *
+ * In pseudo code, this implementation does the following:
+ *
+ * for each node {
+ * have_device_type = false
+ * have_reg = false
+ *
+ * for each property {
+ * if property value == 'memory' {
+ * if property name == 'device_type' {
+ * have_device_type = true
+ * }
+ * } else {
+ * if property name == 'reg' {
+ * have_reg = true
+ * membase = property value[0]
+ * memsize = property value[1]
+ * }
+ * }
+ * }
+ * if have_device_type and have_reg {
+ * return membase and memsize
+ * }
+ * }
+ * return NOT_FOUND
+ */
+
+#define FDT_MAGIC 0xedfe0dd0
+
+#define FDT_BEGIN_NODE 0x1
+#define FDT_END_NODE 0x2
+#define FDT_PROP 0x3
+#define FDT_END 0x9
+
+ xMEMSIZE .req x0 // recorded system RAM size
+ xMEMBASE .req x1 // recorded system RAM base
+
+ xLR .req x8 // our preserved link register
+ xDTP .req x9 // pointer to traverse the DT structure
+ xSTRTAB .req x10 // pointer to the DTB string table
+ xMEMNODE .req x11 // bit field to record found properties
+
+#define HAVE_REG 0x1
+#define HAVE_DEVICE_TYPE 0x2
+
+ .text
+ .align 3
+_memory:
+ .asciz "memory"
+_reg:
+ .asciz "reg"
+_device_type:
+ .asciz "device_type"
+
+ /*
+ * Compare strings in x4 and x5, return in w7
+ */
+ .align 3
+strcmp:
+ ldrb w2, [x4], #1
+ ldrb w3, [x5], #1
+ subs w7, w2, w3
+ cbz w2, 0f
+ cbz w3, 0f
+ beq strcmp
+0: ret
+
+ .globl find_memnode
+find_memnode:
+ // preserve link register
+ mov xLR, x30
+ mov xDTP, x0
+
+ /*
+ * Check the DTB magic at offset 0
+ */
+ movz w4, #:abs_g0_nc:FDT_MAGIC
+ movk w4, #:abs_g1:FDT_MAGIC
+ ldr w5, [xDTP]
+ cmp w4, w5
+ bne err_invalid_magic
+
+ /*
+ * Read the string offset and store it for later use
+ */
+ ldr w4, [xDTP, #12]
+ rev w4, w4
+ add xSTRTAB, xDTP, x4
+
+ /*
+ * Read the struct offset and add it to the DT pointer
+ */
+ ldr w5, [xDTP, #8]
+ rev w5, w5
+ add xDTP, xDTP, x5
+
+ /*
+ * Check current tag for FDT_BEGIN_NODE
+ */
+ ldr w5, [xDTP]
+ rev w5, w5
+ cmp w5, #FDT_BEGIN_NODE
+ bne err_unexpected_begin_tag
+
+begin_node:
+ mov xMEMNODE, #0
+ add xDTP, xDTP, #4
+
+ /*
+ * Advance xDTP past NULL terminated string
+ */
+0: ldrb w4, [xDTP], #1
+ cbnz w4, 0b
+
+next_tag:
+ /*
+ * Align the DT pointer xDTP to the next 32-bit boundary
+ */
+ add xDTP, xDTP, #3
+ and xDTP, xDTP, #~3
+
+ /*
+ * Read the next tag, could be BEGIN_NODE, END_NODE, PROP, END
+ */
+ ldr w5, [xDTP]
+ rev w5, w5
+ cmp w5, #FDT_BEGIN_NODE
+ beq begin_node
+ cmp w5, #FDT_END_NODE
+ beq end_node
+ cmp w5, #FDT_PROP
+ beq prop_node
+ cmp w5, #FDT_END
+ beq err_end_of_fdt
+ b err_unexpected_tag
+
+prop_node:
+ /*
+ * If propname == 'reg', record as membase and memsize
+ * If propname == 'device_type' and value == 'memory',
+ * set the 'is_memnode' flag for this node
+ */
+ ldr w6, [xDTP, #4]
+ add xDTP, xDTP, #12
+ rev w6, w6
+ mov x5, xDTP
+ adr x4, _memory
+ bl strcmp
+
+ /*
+ * Get handle to property name
+ */
+ ldr w5, [xDTP, #-4]
+ rev w5, w5
+ add x5, xSTRTAB, x5
+
+ cbz w7, check_device_type
+
+ /*
+ * Check for 'reg' property
+ */
+ adr x4, _reg
+ bl strcmp
+ cbnz w7, inc_and_next_tag
+
+ /*
+ * Extract two 64-bit quantities from the 'reg' property. These values
+ * will only be used if the node also turns out to have a device_type
+ * property with a value of 'memory'.
+ *
+ * NOTE: xDTP is only guaranteed to be 32 bit aligned, and we are most
+ * likely executing with the MMU off, so we cannot use 64 bit
+ * wide accesses here.
+ */
+ ldp w4, w5, [xDTP]
+ orr xMEMBASE, x4, x5, lsl #32
+ ldp w4, w5, [xDTP, #8]
+ orr xMEMSIZE, x4, x5, lsl #32
+ rev xMEMBASE, xMEMBASE
+ rev xMEMSIZE, xMEMSIZE
+ orr xMEMNODE, xMEMNODE, #HAVE_REG
+ b inc_and_next_tag
+
+check_device_type:
+ /*
+ * Check whether the current property's name is 'device_type'
+ */
+ adr x4, _device_type
+ bl strcmp
+ cbnz w7, inc_and_next_tag
+ orr xMEMNODE, xMEMNODE, #HAVE_DEVICE_TYPE
+
+inc_and_next_tag:
+ add xDTP, xDTP, x6
+ b next_tag
+
+end_node:
+ /*
+ * Check for device_type = memory and reg = xxxx
+ * If we have both, we are done
+ */
+ add xDTP, xDTP, #4
+ cmp xMEMNODE, #(HAVE_REG | HAVE_DEVICE_TYPE)
+ bne next_tag
+
+ ret xLR
+
+err_invalid_magic:
+err_unexpected_begin_tag:
+err_unexpected_tag:
+err_end_of_fdt:
+ wfi
diff --git a/ArmVirtPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/RelocatableVirtHelper.S b/ArmVirtPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/RelocatableVirtHelper.S
new file mode 100644
index 0000000000..d6edc62efc
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/RelocatableVirtHelper.S
@@ -0,0 +1,167 @@
+#
+# Copyright (c) 2011-2013, ARM Limited. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+
+#include <AsmMacroIoLibV8.h>
+#include <Base.h>
+#include <Library/ArmLib.h>
+#include <Library/PcdLib.h>
+#include <AutoGen.h>
+
+.text
+.align 2
+
+GCC_ASM_EXPORT(ArmPlatformPeiBootAction)
+GCC_ASM_EXPORT(ArmPlatformIsPrimaryCore)
+GCC_ASM_EXPORT(ArmPlatformGetPrimaryCoreMpId)
+GCC_ASM_EXPORT(ArmPlatformGetCorePosition)
+GCC_ASM_EXPORT(ArmGetPhysAddrTop)
+
+GCC_ASM_IMPORT(_gPcd_FixedAtBuild_PcdArmPrimaryCore)
+GCC_ASM_IMPORT(_gPcd_FixedAtBuild_PcdArmPrimaryCoreMask)
+GCC_ASM_IMPORT(_gPcd_FixedAtBuild_PcdCoreCount)
+
+.LFdtMagic:
+ .byte 0xd0, 0x0d, 0xfe, 0xed
+
+.LArm64LinuxMagic:
+ .byte 0x41, 0x52, 0x4d, 0x64
+
+// VOID
+// ArmPlatformPeiBootAction (
+// VOID *DeviceTreeBaseAddress, // passed by loader in x0
+// VOID *ImageBase // passed by FDF trampoline in x1
+// );
+ASM_PFX(ArmPlatformPeiBootAction):
+ mov x29, x30 // preserve LR
+
+ //
+ // If we are booting from RAM using the Linux kernel boot protocol, x0 will
+ // point to the DTB image in memory. Otherwise, we are just coming out of
+ // reset, and x0 will be 0. Check also the FDT magic.
+ //
+ cbz x0, .Lout
+ ldr w8, .LFdtMagic
+ ldr w9, [x0]
+ cmp w8, w9
+ bne .Lout
+
+ //
+ // The base of the runtime image has been preserved in x1. Check whether
+ // the expected magic number can be found in the header.
+ //
+ ldr w8, .LArm64LinuxMagic
+ ldr w9, [x1, #0x38]
+ cmp w8, w9
+ bne .Lout
+
+ //
+ //
+ // OK, so far so good. We have confirmed that we likely have a DTB and are
+ // booting via the arm64 Linux boot protocol. Update the base-of-image PCD
+ // to the actual relocated value, and add the shift of PcdFdBaseAddress to
+ // PcdFvBaseAddress as well
+ //
+ adr x8, PcdGet64 (PcdFdBaseAddress)
+ adr x9, PcdGet64 (PcdFvBaseAddress)
+ ldr x6, [x8]
+ ldr x7, [x9]
+ sub x7, x7, x6
+ add x7, x7, x1
+ str x1, [x8]
+ str x7, [x9]
+
+ //
+ // Copy the DTB to the slack space right after the 64 byte arm64/Linux style
+ // image header at the base of this image (defined in the FDF), and record the
+ // pointer in PcdDeviceTreeInitialBaseAddress.
+ //
+ adr x8, PcdGet64 (PcdDeviceTreeInitialBaseAddress)
+ add x1, x1, #0x40
+ str x1, [x8]
+
+ ldr w8, [x0, #4] // get DTB size (BE)
+ mov x9, x1
+ rev w8, w8
+ add x8, x8, x0
+0:ldp x6, x7, [x0], #16
+ stp x6, x7, [x9], #16
+ cmp x0, x8
+ blt 0b
+
+ //
+ // Discover the memory size and offset from the DTB, and record in the
+ // respective PCDs
+ //
+ mov x0, x1
+ bl find_memnode // returns (size, base) size in (x0, x1)
+ cbz x0, .Lout
+
+ adr x8, PcdGet64 (PcdSystemMemorySize)
+ adr x9, PcdGet64 (PcdSystemMemoryBase)
+ str x0, [x8]
+ str x1, [x9]
+
+.Lout:
+ ret x29
+
+//UINTN
+//ArmPlatformGetPrimaryCoreMpId (
+// VOID
+// );
+ASM_PFX(ArmPlatformGetPrimaryCoreMpId):
+ LoadConstantToReg (_gPcd_FixedAtBuild_PcdArmPrimaryCore, x0)
+ ldrh w0, [x0]
+ ret
+
+//UINTN
+//ArmPlatformIsPrimaryCore (
+// IN UINTN MpId
+// );
+ASM_PFX(ArmPlatformIsPrimaryCore):
+ mov x0, #1
+ ret
+
+//UINTN
+//ArmPlatformGetCorePosition (
+// IN UINTN MpId
+// );
+// With this function: CorePos = (ClusterId * 4) + CoreId
+ASM_PFX(ArmPlatformGetCorePosition):
+ and x1, x0, #ARM_CORE_MASK
+ and x0, x0, #ARM_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+
+//EFI_PHYSICAL_ADDRESS
+//GetPhysAddrTop (
+// VOID
+// );
+ASM_PFX(ArmGetPhysAddrTop):
+ mrs x0, id_aa64mmfr0_el1
+ adr x1, .LPARanges
+ and x0, x0, #7
+ ldrb w1, [x1, x0]
+ mov x0, #1
+ lsl x0, x0, x1
+ ret
+
+//
+// Bits 0..2 of the AA64MFR0_EL1 system register encode the size of the
+// physical address space support on this CPU:
+// 0 == 32 bits, 1 == 36 bits, etc etc
+// 6 and 7 are reserved
+//
+.LPARanges:
+ .byte 32, 36, 40, 42, 44, 48, -1, -1
+
+ASM_FUNCTION_REMOVE_IF_UNREFERENCED
diff --git a/ArmVirtPkg/Library/ArmXenRelocatablePlatformLib/ArmXenRelocatablePlatformLib.inf b/ArmVirtPkg/Library/ArmXenRelocatablePlatformLib/ArmXenRelocatablePlatformLib.inf
new file mode 100644
index 0000000000..1afab21576
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmXenRelocatablePlatformLib/ArmXenRelocatablePlatformLib.inf
@@ -0,0 +1,59 @@
+#/* @file
+# Copyright (c) 2011-2015, ARM Limited. All rights reserved.
+# Copyright (c) 2014, Linaro Limited. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmXenRelocatablePlatformLib
+ FILE_GUID = c8602718-4faa-4119-90ca-cae72509ac4c
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmPlatformLib|SEC PEIM
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ ArmVirtPkg/ArmVirtPkg.dec
+
+[LibraryClasses]
+ IoLib
+ ArmLib
+ PrintLib
+
+[Sources.common]
+ RelocatableVirt.c
+ XenVirtMem.c
+
+[Sources.AARCH64]
+ AARCH64/RelocatableVirtHelper.S
+ AARCH64/MemnodeParser.S
+
+[FeaturePcd]
+ gEmbeddedTokenSpaceGuid.PcdCacheEnable
+ gArmPlatformTokenSpaceGuid.PcdSystemMemoryInitializeInSec
+
+[PatchPcd]
+ gArmVirtTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress
+ gArmTokenSpaceGuid.PcdFdBaseAddress
+ gArmTokenSpaceGuid.PcdFvBaseAddress
+ gArmTokenSpaceGuid.PcdSystemMemoryBase
+ gArmTokenSpaceGuid.PcdSystemMemorySize
+
+[FixedPcd]
+ gArmPlatformTokenSpaceGuid.PcdCoreCount
+ gArmTokenSpaceGuid.PcdArmPrimaryCoreMask
+ gArmTokenSpaceGuid.PcdArmPrimaryCore
+ gArmTokenSpaceGuid.PcdFdSize
diff --git a/ArmVirtPkg/Library/ArmXenRelocatablePlatformLib/RelocatableVirt.c b/ArmVirtPkg/Library/ArmXenRelocatablePlatformLib/RelocatableVirt.c
new file mode 100644
index 0000000000..c10c09fed2
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmXenRelocatablePlatformLib/RelocatableVirt.c
@@ -0,0 +1,71 @@
+/** @file
+*
+* Copyright (c) 2011-2013, ARM Limited. All rights reserved.
+* Copyright (c) 2014, Linaro Limited. All rights reserved.
+* Copyright (c) 2014, Red Hat, Inc.
+*
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Library/IoLib.h>
+#include <Library/ArmPlatformLib.h>
+#include <Library/DebugLib.h>
+#include <ArmPlatform.h>
+#include <Pi/PiBootMode.h>
+
+/**
+ Return the current Boot Mode
+
+ This function returns the boot reason on the platform
+
+ @return Return the current Boot Mode of the platform
+
+**/
+EFI_BOOT_MODE
+ArmPlatformGetBootMode (
+ VOID
+ )
+{
+ return BOOT_WITH_FULL_CONFIGURATION;
+}
+
+/**
+ This function is called by PrePeiCore, in the SEC phase.
+**/
+RETURN_STATUS
+ArmPlatformInitialize (
+ IN UINTN MpId
+ )
+{
+ //
+ // We are relying on ArmPlatformInitializeSystemMemory () being called from
+ // InitializeMemory (), which only occurs if the following feature is disabled
+ //
+ ASSERT (!FeaturePcdGet (PcdSystemMemoryInitializeInSec));
+ return RETURN_SUCCESS;
+}
+
+VOID
+ArmPlatformInitializeSystemMemory (
+ VOID
+ )
+{
+}
+
+VOID
+ArmPlatformGetPlatformPpiList (
+ OUT UINTN *PpiListSize,
+ OUT EFI_PEI_PPI_DESCRIPTOR **PpiList
+ )
+{
+ *PpiListSize = 0;
+ *PpiList = NULL;
+}
diff --git a/ArmVirtPkg/Library/ArmXenRelocatablePlatformLib/XenVirtMem.c b/ArmVirtPkg/Library/ArmXenRelocatablePlatformLib/XenVirtMem.c
new file mode 100644
index 0000000000..657b840059
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmXenRelocatablePlatformLib/XenVirtMem.c
@@ -0,0 +1,83 @@
+/** @file
+*
+* Copyright (c) 2014, Linaro Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Library/ArmPlatformLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <ArmPlatform.h>
+
+// Number of Virtual Memory Map Descriptors
+#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS 2
+
+// DDR attributes
+#define DDR_ATTRIBUTES_CACHED ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK
+#define DDR_ATTRIBUTES_UNCACHED ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED
+
+EFI_PHYSICAL_ADDRESS
+ArmGetPhysAddrTop (
+ VOID
+ );
+
+/**
+ Return the Virtual Memory Map of your platform
+
+ This Virtual Memory Map is used by MemoryInitPei Module to initialize the MMU
+ on your platform.
+
+ @param[out] VirtualMemoryMap Array of ARM_MEMORY_REGION_DESCRIPTOR
+ describing a Physical-to-Virtual Memory
+ mapping. This array must be ended by a
+ zero-filled entry
+
+**/
+VOID
+ArmPlatformGetVirtualMemoryMap (
+ IN ARM_MEMORY_REGION_DESCRIPTOR** VirtualMemoryMap
+ )
+{
+ ARM_MEMORY_REGION_DESCRIPTOR *VirtualMemoryTable;
+
+ ASSERT (VirtualMemoryMap != NULL);
+
+ VirtualMemoryTable = AllocatePages (
+ EFI_SIZE_TO_PAGES (
+ sizeof (ARM_MEMORY_REGION_DESCRIPTOR)
+ * MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS
+ )
+ );
+
+ if (VirtualMemoryTable == NULL) {
+ DEBUG ((EFI_D_ERROR, "%a: Error: Failed AllocatePages()\n", __FUNCTION__));
+ return;
+ }
+
+ //
+ // Map the entire physical memory space as cached. The only device
+ // we care about is the GIC, which will be stage 2 mapped as a device
+ // by the hypervisor, which will override the cached mapping we install
+ // here.
+ //
+ VirtualMemoryTable[0].PhysicalBase = 0x0;
+ VirtualMemoryTable[0].VirtualBase = 0x0;
+ VirtualMemoryTable[0].Length = ArmGetPhysAddrTop ();
+ VirtualMemoryTable[0].Attributes = DDR_ATTRIBUTES_CACHED;
+
+ // End of Table
+ ZeroMem (&VirtualMemoryTable[1], sizeof (ARM_MEMORY_REGION_DESCRIPTOR));
+
+ *VirtualMemoryMap = VirtualMemoryTable;
+}
diff --git a/ArmVirtPkg/Library/BaseCachingPciExpressLib/BaseCachingPciExpressLib.inf b/ArmVirtPkg/Library/BaseCachingPciExpressLib/BaseCachingPciExpressLib.inf
new file mode 100644
index 0000000000..f6a346d49f
--- /dev/null
+++ b/ArmVirtPkg/Library/BaseCachingPciExpressLib/BaseCachingPciExpressLib.inf
@@ -0,0 +1,46 @@
+## @file
+# Instance of PCI Express Library using the 256 MB PCI Express MMIO window.
+#
+# PCI Express Library that uses the 256 MB PCI Express MMIO window to perform
+# PCI Configuration cycles. Layers on top of an I/O Library instance.
+#
+# Copyright (c) 2007 - 2014, Intel Corporation. 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 = BaseCachingPciExpressLib
+ FILE_GUID = 3f3ffd80-04dc-4a2b-9d25-ecca55c2e520
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PciExpressLib|DXE_DRIVER UEFI_DRIVER UEFI_APPLICATION
+ CONSTRUCTOR = PciExpressLibInitialize
+
+#
+# VALID_ARCHITECTURES = ARM AARCH64
+#
+
+[Sources]
+ PciExpressLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ PcdLib
+ DebugLib
+ IoLib
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## CONSUMES
+
diff --git a/ArmVirtPkg/Library/BaseCachingPciExpressLib/PciExpressLib.c b/ArmVirtPkg/Library/BaseCachingPciExpressLib/PciExpressLib.c
new file mode 100644
index 0000000000..6479f53b37
--- /dev/null
+++ b/ArmVirtPkg/Library/BaseCachingPciExpressLib/PciExpressLib.c
@@ -0,0 +1,1429 @@
+/** @file
+ Functions in this library instance make use of MMIO functions in IoLib to
+ access memory mapped PCI configuration space.
+
+ All assertions for I/O operations are handled in MMIO functions in the IoLib
+ Library.
+
+ Copyright (c) 2006 - 2012, Intel Corporation. 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/BaseLib.h>
+#include <Library/PciExpressLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+
+
+/**
+ Assert the validity of a PCI address. A valid PCI address should contain 1's
+ only in the low 28 bits.
+
+ @param A The address to validate.
+
+**/
+#define ASSERT_INVALID_PCI_ADDRESS(A) \
+ ASSERT (((A) & ~0xfffffff) == 0)
+
+/**
+ Registers a PCI device so PCI configuration registers may be accessed after
+ SetVirtualAddressMap().
+
+ Registers the PCI device specified by Address so all the PCI configuration
+ registers associated with that PCI device may be accessed after SetVirtualAddressMap()
+ is called.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param Address The address that encodes the PCI Bus, Device, Function and
+ Register.
+
+ @retval RETURN_SUCCESS The PCI device was registered for runtime access.
+ @retval RETURN_UNSUPPORTED An attempt was made to call this function
+ after ExitBootServices().
+ @retval RETURN_UNSUPPORTED The resources required to access the PCI device
+ at runtime could not be mapped.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to
+ complete the registration.
+
+**/
+RETURN_STATUS
+EFIAPI
+PciExpressRegisterForRuntimeAccess (
+ IN UINTN Address
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return RETURN_UNSUPPORTED;
+}
+
+STATIC UINT64 mPciExpressBaseAddress;
+
+RETURN_STATUS
+EFIAPI
+PciExpressLibInitialize (
+ VOID
+ )
+{
+ mPciExpressBaseAddress = PcdGet64 (PcdPciExpressBaseAddress);
+ return RETURN_SUCCESS;
+}
+
+
+/**
+ Gets the base address of PCI Express.
+
+ @return The base address of PCI Express.
+
+**/
+VOID*
+GetPciExpressBaseAddress (
+ VOID
+ )
+{
+ return (VOID*)(UINTN) mPciExpressBaseAddress;
+}
+
+/**
+ Reads an 8-bit PCI configuration register.
+
+ Reads and returns the 8-bit PCI configuration register specified by Address.
+ This function must guarantee that all PCI read and write operations are
+ serialized.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param Address The address that encodes the PCI Bus, Device, Function and
+ Register.
+
+ @return The read value from the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressRead8 (
+ IN UINTN Address
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioRead8 ((UINTN) GetPciExpressBaseAddress () + Address);
+}
+
+/**
+ Writes an 8-bit PCI configuration register.
+
+ Writes the 8-bit PCI configuration register specified by Address with the
+ value specified by Value. Value is returned. This function must guarantee
+ that all PCI read and write operations are serialized.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param Address The address that encodes the PCI Bus, Device, Function and
+ Register.
+ @param Value The value to write.
+
+ @return The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressWrite8 (
+ IN UINTN Address,
+ IN UINT8 Value
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioWrite8 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
+}
+
+/**
+ Performs a bitwise OR of an 8-bit PCI configuration register with
+ an 8-bit value.
+
+ Reads the 8-bit PCI configuration register specified by Address, performs a
+ bitwise OR between the read result and the value specified by
+ OrData, and writes the result to the 8-bit PCI configuration register
+ specified by Address. The value written to the PCI configuration register is
+ returned. This function must guarantee that all PCI read and write operations
+ are serialized.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param Address The address that encodes the PCI Bus, Device, Function and
+ Register.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressOr8 (
+ IN UINTN Address,
+ IN UINT8 OrData
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioOr8 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
+}
+
+/**
+ Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
+ value.
+
+ Reads the 8-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData, and
+ writes the result to the 8-bit PCI configuration register specified by
+ Address. The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are
+ serialized.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param Address The address that encodes the PCI Bus, Device, Function and
+ Register.
+ @param AndData The value to AND with the PCI configuration register.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressAnd8 (
+ IN UINTN Address,
+ IN UINT8 AndData
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioAnd8 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
+}
+
+/**
+ Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit
+ value, followed a bitwise OR with another 8-bit value.
+
+ Reads the 8-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData,
+ performs a bitwise OR between the result of the AND operation and
+ the value specified by OrData, and writes the result to the 8-bit PCI
+ configuration register specified by Address. The value written to the PCI
+ configuration register is returned. This function must guarantee that all PCI
+ read and write operations are serialized.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param Address The address that encodes the PCI Bus, Device, Function and
+ Register.
+ @param AndData The value to AND with the PCI configuration register.
+ @param OrData The value to OR with the result of the AND operation.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressAndThenOr8 (
+ IN UINTN Address,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioAndThenOr8 (
+ (UINTN) GetPciExpressBaseAddress () + Address,
+ AndData,
+ OrData
+ );
+}
+
+/**
+ Reads a bit field of a PCI configuration register.
+
+ Reads the bit field in an 8-bit PCI configuration register. The bit field is
+ specified by the StartBit and the EndBit. The value of the bit field is
+ returned.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If StartBit is greater than 7, then ASSERT().
+ If EndBit is greater than 7, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param Address The PCI configuration register to read.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..7.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..7.
+
+ @return The value of the bit field read from the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressBitFieldRead8 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioBitFieldRead8 (
+ (UINTN) GetPciExpressBaseAddress () + Address,
+ StartBit,
+ EndBit
+ );
+}
+
+/**
+ Writes a bit field to a PCI configuration register.
+
+ Writes Value to the bit field of the PCI configuration register. The bit
+ field is specified by the StartBit and the EndBit. All other bits in the
+ destination PCI configuration register are preserved. The new value of the
+ 8-bit register is returned.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If StartBit is greater than 7, then ASSERT().
+ If EndBit is greater than 7, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+ If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address The PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..7.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..7.
+ @param Value The new value of the bit field.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressBitFieldWrite8 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT8 Value
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioBitFieldWrite8 (
+ (UINTN) GetPciExpressBaseAddress () + Address,
+ StartBit,
+ EndBit,
+ Value
+ );
+}
+
+/**
+ Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and
+ writes the result back to the bit field in the 8-bit port.
+
+ Reads the 8-bit PCI configuration register specified by Address, performs a
+ bitwise OR between the read result and the value specified by
+ OrData, and writes the result to the 8-bit PCI configuration register
+ specified by Address. The value written to the PCI configuration register is
+ returned. This function must guarantee that all PCI read and write operations
+ are serialized. Extra left bits in OrData are stripped.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If StartBit is greater than 7, then ASSERT().
+ If EndBit is greater than 7, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+ If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address The PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..7.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..7.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressBitFieldOr8 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT8 OrData
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioBitFieldOr8 (
+ (UINTN) GetPciExpressBaseAddress () + Address,
+ StartBit,
+ EndBit,
+ OrData
+ );
+}
+
+/**
+ Reads a bit field in an 8-bit PCI configuration register, performs a bitwise
+ AND, and writes the result back to the bit field in the 8-bit register.
+
+ Reads the 8-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData, and
+ writes the result to the 8-bit PCI configuration register specified by
+ Address. The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are
+ serialized. Extra left bits in AndData are stripped.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If StartBit is greater than 7, then ASSERT().
+ If EndBit is greater than 7, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+ If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address The PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..7.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..7.
+ @param AndData The value to AND with the PCI configuration register.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressBitFieldAnd8 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT8 AndData
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioBitFieldAnd8 (
+ (UINTN) GetPciExpressBaseAddress () + Address,
+ StartBit,
+ EndBit,
+ AndData
+ );
+}
+
+/**
+ Reads a bit field in an 8-bit port, performs a bitwise AND followed by a
+ bitwise OR, and writes the result back to the bit field in the
+ 8-bit port.
+
+ Reads the 8-bit PCI configuration register specified by Address, performs a
+ bitwise AND followed by a bitwise OR between the read result and
+ the value specified by AndData, and writes the result to the 8-bit PCI
+ configuration register specified by Address. The value written to the PCI
+ configuration register is returned. This function must guarantee that all PCI
+ read and write operations are serialized. Extra left bits in both AndData and
+ OrData are stripped.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If StartBit is greater than 7, then ASSERT().
+ If EndBit is greater than 7, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+ If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+ If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address The PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..7.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..7.
+ @param AndData The value to AND with the PCI configuration register.
+ @param OrData The value to OR with the result of the AND operation.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressBitFieldAndThenOr8 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioBitFieldAndThenOr8 (
+ (UINTN) GetPciExpressBaseAddress () + Address,
+ StartBit,
+ EndBit,
+ AndData,
+ OrData
+ );
+}
+
+/**
+ Reads a 16-bit PCI configuration register.
+
+ Reads and returns the 16-bit PCI configuration register specified by Address.
+ This function must guarantee that all PCI read and write operations are
+ serialized.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+ @param Address The address that encodes the PCI Bus, Device, Function and
+ Register.
+
+ @return The read value from the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressRead16 (
+ IN UINTN Address
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioRead16 ((UINTN) GetPciExpressBaseAddress () + Address);
+}
+
+/**
+ Writes a 16-bit PCI configuration register.
+
+ Writes the 16-bit PCI configuration register specified by Address with the
+ value specified by Value. Value is returned. This function must guarantee
+ that all PCI read and write operations are serialized.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+ @param Address The address that encodes the PCI Bus, Device, Function and
+ Register.
+ @param Value The value to write.
+
+ @return The value written to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressWrite16 (
+ IN UINTN Address,
+ IN UINT16 Value
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioWrite16 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
+}
+
+/**
+ Performs a bitwise OR of a 16-bit PCI configuration register with
+ a 16-bit value.
+
+ Reads the 16-bit PCI configuration register specified by Address, performs a
+ bitwise OR between the read result and the value specified by
+ OrData, and writes the result to the 16-bit PCI configuration register
+ specified by Address. The value written to the PCI configuration register is
+ returned. This function must guarantee that all PCI read and write operations
+ are serialized.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+ @param Address The address that encodes the PCI Bus, Device, Function and
+ Register.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressOr16 (
+ IN UINTN Address,
+ IN UINT16 OrData
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioOr16 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
+}
+
+/**
+ Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
+ value.
+
+ Reads the 16-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData, and
+ writes the result to the 16-bit PCI configuration register specified by
+ Address. The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are
+ serialized.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+ @param Address The address that encodes the PCI Bus, Device, Function and
+ Register.
+ @param AndData The value to AND with the PCI configuration register.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressAnd16 (
+ IN UINTN Address,
+ IN UINT16 AndData
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioAnd16 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
+}
+
+/**
+ Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit
+ value, followed a bitwise OR with another 16-bit value.
+
+ Reads the 16-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData,
+ performs a bitwise OR between the result of the AND operation and
+ the value specified by OrData, and writes the result to the 16-bit PCI
+ configuration register specified by Address. The value written to the PCI
+ configuration register is returned. This function must guarantee that all PCI
+ read and write operations are serialized.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+ @param Address The address that encodes the PCI Bus, Device, Function and
+ Register.
+ @param AndData The value to AND with the PCI configuration register.
+ @param OrData The value to OR with the result of the AND operation.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressAndThenOr16 (
+ IN UINTN Address,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioAndThenOr16 (
+ (UINTN) GetPciExpressBaseAddress () + Address,
+ AndData,
+ OrData
+ );
+}
+
+/**
+ Reads a bit field of a PCI configuration register.
+
+ Reads the bit field in a 16-bit PCI configuration register. The bit field is
+ specified by the StartBit and the EndBit. The value of the bit field is
+ returned.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+ If StartBit is greater than 15, then ASSERT().
+ If EndBit is greater than 15, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param Address The PCI configuration register to read.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..15.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..15.
+
+ @return The value of the bit field read from the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressBitFieldRead16 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioBitFieldRead16 (
+ (UINTN) GetPciExpressBaseAddress () + Address,
+ StartBit,
+ EndBit
+ );
+}
+
+/**
+ Writes a bit field to a PCI configuration register.
+
+ Writes Value to the bit field of the PCI configuration register. The bit
+ field is specified by the StartBit and the EndBit. All other bits in the
+ destination PCI configuration register are preserved. The new value of the
+ 16-bit register is returned.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+ If StartBit is greater than 15, then ASSERT().
+ If EndBit is greater than 15, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+ If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address The PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..15.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..15.
+ @param Value The new value of the bit field.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressBitFieldWrite16 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT16 Value
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioBitFieldWrite16 (
+ (UINTN) GetPciExpressBaseAddress () + Address,
+ StartBit,
+ EndBit,
+ Value
+ );
+}
+
+/**
+ Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and
+ writes the result back to the bit field in the 16-bit port.
+
+ Reads the 16-bit PCI configuration register specified by Address, performs a
+ bitwise OR between the read result and the value specified by
+ OrData, and writes the result to the 16-bit PCI configuration register
+ specified by Address. The value written to the PCI configuration register is
+ returned. This function must guarantee that all PCI read and write operations
+ are serialized. Extra left bits in OrData are stripped.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+ If StartBit is greater than 15, then ASSERT().
+ If EndBit is greater than 15, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+ If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address The PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..15.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..15.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressBitFieldOr16 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT16 OrData
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioBitFieldOr16 (
+ (UINTN) GetPciExpressBaseAddress () + Address,
+ StartBit,
+ EndBit,
+ OrData
+ );
+}
+
+/**
+ Reads a bit field in a 16-bit PCI configuration register, performs a bitwise
+ AND, and writes the result back to the bit field in the 16-bit register.
+
+ Reads the 16-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData, and
+ writes the result to the 16-bit PCI configuration register specified by
+ Address. The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are
+ serialized. Extra left bits in AndData are stripped.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+ If StartBit is greater than 15, then ASSERT().
+ If EndBit is greater than 15, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+ If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address The PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..15.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..15.
+ @param AndData The value to AND with the PCI configuration register.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressBitFieldAnd16 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT16 AndData
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioBitFieldAnd16 (
+ (UINTN) GetPciExpressBaseAddress () + Address,
+ StartBit,
+ EndBit,
+ AndData
+ );
+}
+
+/**
+ Reads a bit field in a 16-bit port, performs a bitwise AND followed by a
+ bitwise OR, and writes the result back to the bit field in the
+ 16-bit port.
+
+ Reads the 16-bit PCI configuration register specified by Address, performs a
+ bitwise AND followed by a bitwise OR between the read result and
+ the value specified by AndData, and writes the result to the 16-bit PCI
+ configuration register specified by Address. The value written to the PCI
+ configuration register is returned. This function must guarantee that all PCI
+ read and write operations are serialized. Extra left bits in both AndData and
+ OrData are stripped.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+ If StartBit is greater than 15, then ASSERT().
+ If EndBit is greater than 15, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+ If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+ If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address The PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..15.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..15.
+ @param AndData The value to AND with the PCI configuration register.
+ @param OrData The value to OR with the result of the AND operation.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressBitFieldAndThenOr16 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioBitFieldAndThenOr16 (
+ (UINTN) GetPciExpressBaseAddress () + Address,
+ StartBit,
+ EndBit,
+ AndData,
+ OrData
+ );
+}
+
+/**
+ Reads a 32-bit PCI configuration register.
+
+ Reads and returns the 32-bit PCI configuration register specified by Address.
+ This function must guarantee that all PCI read and write operations are
+ serialized.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param Address The address that encodes the PCI Bus, Device, Function and
+ Register.
+
+ @return The read value from the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressRead32 (
+ IN UINTN Address
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioRead32 ((UINTN) GetPciExpressBaseAddress () + Address);
+}
+
+/**
+ Writes a 32-bit PCI configuration register.
+
+ Writes the 32-bit PCI configuration register specified by Address with the
+ value specified by Value. Value is returned. This function must guarantee
+ that all PCI read and write operations are serialized.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param Address The address that encodes the PCI Bus, Device, Function and
+ Register.
+ @param Value The value to write.
+
+ @return The value written to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressWrite32 (
+ IN UINTN Address,
+ IN UINT32 Value
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioWrite32 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
+}
+
+/**
+ Performs a bitwise OR of a 32-bit PCI configuration register with
+ a 32-bit value.
+
+ Reads the 32-bit PCI configuration register specified by Address, performs a
+ bitwise OR between the read result and the value specified by
+ OrData, and writes the result to the 32-bit PCI configuration register
+ specified by Address. The value written to the PCI configuration register is
+ returned. This function must guarantee that all PCI read and write operations
+ are serialized.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param Address The address that encodes the PCI Bus, Device, Function and
+ Register.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressOr32 (
+ IN UINTN Address,
+ IN UINT32 OrData
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioOr32 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
+}
+
+/**
+ Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
+ value.
+
+ Reads the 32-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData, and
+ writes the result to the 32-bit PCI configuration register specified by
+ Address. The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are
+ serialized.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param Address The address that encodes the PCI Bus, Device, Function and
+ Register.
+ @param AndData The value to AND with the PCI configuration register.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressAnd32 (
+ IN UINTN Address,
+ IN UINT32 AndData
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioAnd32 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
+}
+
+/**
+ Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit
+ value, followed a bitwise OR with another 32-bit value.
+
+ Reads the 32-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData,
+ performs a bitwise OR between the result of the AND operation and
+ the value specified by OrData, and writes the result to the 32-bit PCI
+ configuration register specified by Address. The value written to the PCI
+ configuration register is returned. This function must guarantee that all PCI
+ read and write operations are serialized.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param Address The address that encodes the PCI Bus, Device, Function and
+ Register.
+ @param AndData The value to AND with the PCI configuration register.
+ @param OrData The value to OR with the result of the AND operation.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressAndThenOr32 (
+ IN UINTN Address,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioAndThenOr32 (
+ (UINTN) GetPciExpressBaseAddress () + Address,
+ AndData,
+ OrData
+ );
+}
+
+/**
+ Reads a bit field of a PCI configuration register.
+
+ Reads the bit field in a 32-bit PCI configuration register. The bit field is
+ specified by the StartBit and the EndBit. The value of the bit field is
+ returned.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+ If StartBit is greater than 31, then ASSERT().
+ If EndBit is greater than 31, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param Address The PCI configuration register to read.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..31.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..31.
+
+ @return The value of the bit field read from the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressBitFieldRead32 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioBitFieldRead32 (
+ (UINTN) GetPciExpressBaseAddress () + Address,
+ StartBit,
+ EndBit
+ );
+}
+
+/**
+ Writes a bit field to a PCI configuration register.
+
+ Writes Value to the bit field of the PCI configuration register. The bit
+ field is specified by the StartBit and the EndBit. All other bits in the
+ destination PCI configuration register are preserved. The new value of the
+ 32-bit register is returned.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+ If StartBit is greater than 31, then ASSERT().
+ If EndBit is greater than 31, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+ If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address The PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..31.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..31.
+ @param Value The new value of the bit field.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressBitFieldWrite32 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT32 Value
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioBitFieldWrite32 (
+ (UINTN) GetPciExpressBaseAddress () + Address,
+ StartBit,
+ EndBit,
+ Value
+ );
+}
+
+/**
+ Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and
+ writes the result back to the bit field in the 32-bit port.
+
+ Reads the 32-bit PCI configuration register specified by Address, performs a
+ bitwise OR between the read result and the value specified by
+ OrData, and writes the result to the 32-bit PCI configuration register
+ specified by Address. The value written to the PCI configuration register is
+ returned. This function must guarantee that all PCI read and write operations
+ are serialized. Extra left bits in OrData are stripped.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+ If StartBit is greater than 31, then ASSERT().
+ If EndBit is greater than 31, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+ If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address The PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..31.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..31.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressBitFieldOr32 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT32 OrData
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioBitFieldOr32 (
+ (UINTN) GetPciExpressBaseAddress () + Address,
+ StartBit,
+ EndBit,
+ OrData
+ );
+}
+
+/**
+ Reads a bit field in a 32-bit PCI configuration register, performs a bitwise
+ AND, and writes the result back to the bit field in the 32-bit register.
+
+ Reads the 32-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData, and
+ writes the result to the 32-bit PCI configuration register specified by
+ Address. The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are
+ serialized. Extra left bits in AndData are stripped.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+ If StartBit is greater than 31, then ASSERT().
+ If EndBit is greater than 31, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+ If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address The PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..31.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..31.
+ @param AndData The value to AND with the PCI configuration register.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressBitFieldAnd32 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT32 AndData
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioBitFieldAnd32 (
+ (UINTN) GetPciExpressBaseAddress () + Address,
+ StartBit,
+ EndBit,
+ AndData
+ );
+}
+
+/**
+ Reads a bit field in a 32-bit port, performs a bitwise AND followed by a
+ bitwise OR, and writes the result back to the bit field in the
+ 32-bit port.
+
+ Reads the 32-bit PCI configuration register specified by Address, performs a
+ bitwise AND followed by a bitwise OR between the read result and
+ the value specified by AndData, and writes the result to the 32-bit PCI
+ configuration register specified by Address. The value written to the PCI
+ configuration register is returned. This function must guarantee that all PCI
+ read and write operations are serialized. Extra left bits in both AndData and
+ OrData are stripped.
+
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+ If StartBit is greater than 31, then ASSERT().
+ If EndBit is greater than 31, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+ If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+ If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address The PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..31.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..31.
+ @param AndData The value to AND with the PCI configuration register.
+ @param OrData The value to OR with the result of the AND operation.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressBitFieldAndThenOr32 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ return MmioBitFieldAndThenOr32 (
+ (UINTN) GetPciExpressBaseAddress () + Address,
+ StartBit,
+ EndBit,
+ AndData,
+ OrData
+ );
+}
+
+/**
+ Reads a range of PCI configuration registers into a caller supplied buffer.
+
+ Reads the range of PCI configuration registers specified by StartAddress and
+ Size into the buffer specified by Buffer. This function only allows the PCI
+ configuration registers from a single PCI function to be read. Size is
+ returned. When possible 32-bit PCI configuration read cycles are used to read
+ from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit
+ and 16-bit PCI configuration read cycles may be used at the beginning and the
+ end of the range.
+
+ If StartAddress > 0x0FFFFFFF, then ASSERT().
+ If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
+ If Size > 0 and Buffer is NULL, then ASSERT().
+
+ @param StartAddress The starting address that encodes the PCI Bus, Device,
+ Function and Register.
+ @param Size The size in bytes of the transfer.
+ @param Buffer The pointer to a buffer receiving the data read.
+
+ @return Size read data from StartAddress.
+
+**/
+UINTN
+EFIAPI
+PciExpressReadBuffer (
+ IN UINTN StartAddress,
+ IN UINTN Size,
+ OUT VOID *Buffer
+ )
+{
+ UINTN ReturnValue;
+
+ ASSERT_INVALID_PCI_ADDRESS (StartAddress);
+ ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
+
+ if (Size == 0) {
+ return Size;
+ }
+
+ ASSERT (Buffer != NULL);
+
+ //
+ // Save Size for return
+ //
+ ReturnValue = Size;
+
+ if ((StartAddress & 1) != 0) {
+ //
+ // Read a byte if StartAddress is byte aligned
+ //
+ *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress);
+ StartAddress += sizeof (UINT8);
+ Size -= sizeof (UINT8);
+ Buffer = (UINT8*)Buffer + 1;
+ }
+
+ if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
+ //
+ // Read a word if StartAddress is word aligned
+ //
+ WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 (StartAddress));
+
+ StartAddress += sizeof (UINT16);
+ Size -= sizeof (UINT16);
+ Buffer = (UINT16*)Buffer + 1;
+ }
+
+ while (Size >= sizeof (UINT32)) {
+ //
+ // Read as many double words as possible
+ //
+ WriteUnaligned32 ((UINT32 *) Buffer, (UINT32) PciExpressRead32 (StartAddress));
+
+ StartAddress += sizeof (UINT32);
+ Size -= sizeof (UINT32);
+ Buffer = (UINT32*)Buffer + 1;
+ }
+
+ if (Size >= sizeof (UINT16)) {
+ //
+ // Read the last remaining word if exist
+ //
+ WriteUnaligned16 ((UINT16 *) Buffer, (UINT16) PciExpressRead16 (StartAddress));
+ StartAddress += sizeof (UINT16);
+ Size -= sizeof (UINT16);
+ Buffer = (UINT16*)Buffer + 1;
+ }
+
+ if (Size >= sizeof (UINT8)) {
+ //
+ // Read the last remaining byte if exist
+ //
+ *(volatile UINT8 *)Buffer = PciExpressRead8 (StartAddress);
+ }
+
+ return ReturnValue;
+}
+
+/**
+ Copies the data in a caller supplied buffer to a specified range of PCI
+ configuration space.
+
+ Writes the range of PCI configuration registers specified by StartAddress and
+ Size from the buffer specified by Buffer. This function only allows the PCI
+ configuration registers from a single PCI function to be written. Size is
+ returned. When possible 32-bit PCI configuration write cycles are used to
+ write from StartAdress to StartAddress + Size. Due to alignment restrictions,
+ 8-bit and 16-bit PCI configuration write cycles may be used at the beginning
+ and the end of the range.
+
+ If StartAddress > 0x0FFFFFFF, then ASSERT().
+ If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
+ If Size > 0 and Buffer is NULL, then ASSERT().
+
+ @param StartAddress The starting address that encodes the PCI Bus, Device,
+ Function and Register.
+ @param Size The size in bytes of the transfer.
+ @param Buffer The pointer to a buffer containing the data to write.
+
+ @return Size written to StartAddress.
+
+**/
+UINTN
+EFIAPI
+PciExpressWriteBuffer (
+ IN UINTN StartAddress,
+ IN UINTN Size,
+ IN VOID *Buffer
+ )
+{
+ UINTN ReturnValue;
+
+ ASSERT_INVALID_PCI_ADDRESS (StartAddress);
+ ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
+
+ if (Size == 0) {
+ return 0;
+ }
+
+ ASSERT (Buffer != NULL);
+
+ //
+ // Save Size for return
+ //
+ ReturnValue = Size;
+
+ if ((StartAddress & 1) != 0) {
+ //
+ // Write a byte if StartAddress is byte aligned
+ //
+ PciExpressWrite8 (StartAddress, *(UINT8*)Buffer);
+ StartAddress += sizeof (UINT8);
+ Size -= sizeof (UINT8);
+ Buffer = (UINT8*)Buffer + 1;
+ }
+
+ if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
+ //
+ // Write a word if StartAddress is word aligned
+ //
+ PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer));
+ StartAddress += sizeof (UINT16);
+ Size -= sizeof (UINT16);
+ Buffer = (UINT16*)Buffer + 1;
+ }
+
+ while (Size >= sizeof (UINT32)) {
+ //
+ // Write as many double words as possible
+ //
+ PciExpressWrite32 (StartAddress, ReadUnaligned32 ((UINT32*)Buffer));
+ StartAddress += sizeof (UINT32);
+ Size -= sizeof (UINT32);
+ Buffer = (UINT32*)Buffer + 1;
+ }
+
+ if (Size >= sizeof (UINT16)) {
+ //
+ // Write the last remaining word if exist
+ //
+ PciExpressWrite16 (StartAddress, ReadUnaligned16 ((UINT16*)Buffer));
+ StartAddress += sizeof (UINT16);
+ Size -= sizeof (UINT16);
+ Buffer = (UINT16*)Buffer + 1;
+ }
+
+ if (Size >= sizeof (UINT8)) {
+ //
+ // Write the last remaining byte if exist
+ //
+ PciExpressWrite8 (StartAddress, *(UINT8*)Buffer);
+ }
+
+ return ReturnValue;
+}
diff --git a/ArmVirtPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.c b/ArmVirtPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.c
new file mode 100644
index 0000000000..ba6d277d45
--- /dev/null
+++ b/ArmVirtPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.c
@@ -0,0 +1,185 @@
+/** @file
+ Serial I/O Port library functions with base address discovered from FDT
+
+ Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
+ Copyright (c) 2012 - 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 <Base.h>
+
+#include <Library/PcdLib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/SerialPortExtLib.h>
+#include <libfdt.h>
+
+#include <Drivers/PL011Uart.h>
+
+RETURN_STATUS
+EFIAPI
+SerialPortInitialize (
+ VOID
+ )
+{
+ //
+ // This SerialPortInitialize() function is completely empty, for a number of
+ // reasons:
+ // - if we are executing from flash, it is hard to keep state (i.e., store the
+ // discovered base address in a global), and the most robust way to deal
+ // with this is to discover the base address at every Write ();
+ // - calls to the Write() function in this module may be issued before this
+ // initialization function is called: this is not a problem when the base
+ // address of the UART is hardcoded, and only the baud rate may be wrong,
+ // but if we don't know the base address yet, we may be poking into memory
+ // that does not tolerate being poked into;
+ // - SEC and PEI phases produce debug output only, so with debug disabled, no
+ // initialization (or device tree parsing) is performed at all.
+ //
+ // Note that this means that on *every* Write () call, the device tree will be
+ // parsed and the UART re-initialized. However, this is a small price to pay
+ // for having serial debug output on a UART with no fixed base address.
+ //
+ return RETURN_SUCCESS;
+}
+
+STATIC
+UINT64
+SerialPortGetBaseAddress (
+ VOID
+ )
+{
+ UINT64 BaudRate;
+ UINT32 ReceiveFifoDepth;
+ EFI_PARITY_TYPE Parity;
+ UINT8 DataBits;
+ EFI_STOP_BITS_TYPE StopBits;
+ VOID *DeviceTreeBase;
+ INT32 Node, Prev;
+ INT32 Len;
+ CONST CHAR8 *Compatible;
+ CONST CHAR8 *CompatibleItem;
+ CONST UINT64 *RegProperty;
+ UINTN UartBase;
+ RETURN_STATUS Status;
+
+ DeviceTreeBase = (VOID *)(UINTN)FixedPcdGet64 (PcdDeviceTreeInitialBaseAddress);
+
+ if ((DeviceTreeBase == NULL) || (fdt_check_header (DeviceTreeBase) != 0)) {
+ return 0;
+ }
+
+ //
+ // Enumerate all FDT nodes looking for a PL011 and capture its base address
+ //
+ for (Prev = 0;; Prev = Node) {
+ Node = fdt_next_node (DeviceTreeBase, Prev, NULL);
+ if (Node < 0) {
+ break;
+ }
+
+ Compatible = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len);
+ if (Compatible == NULL) {
+ continue;
+ }
+
+ //
+ // Iterate over the NULL-separated items in the compatible string
+ //
+ for (CompatibleItem = Compatible; CompatibleItem < Compatible + Len;
+ CompatibleItem += 1 + AsciiStrLen (CompatibleItem)) {
+
+ if (AsciiStrCmp (CompatibleItem, "arm,pl011") == 0) {
+ RegProperty = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);
+ if (Len != 16) {
+ return 0;
+ }
+ UartBase = (UINTN)fdt64_to_cpu (ReadUnaligned64 (RegProperty));
+
+ BaudRate = (UINTN)FixedPcdGet64 (PcdUartDefaultBaudRate);
+ ReceiveFifoDepth = 0; // Use the default value for Fifo depth
+ Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity);
+ DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);
+ StopBits = (EFI_STOP_BITS_TYPE) FixedPcdGet8 (PcdUartDefaultStopBits);
+
+ Status = PL011UartInitializePort (
+ UartBase,
+ &BaudRate, &ReceiveFifoDepth, &Parity, &DataBits, &StopBits);
+ if (!EFI_ERROR (Status)) {
+ return UartBase;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ Write data to serial device.
+
+ @param Buffer Point of data buffer which need to be written.
+ @param NumberOfBytes Number of output bytes which are cached in Buffer.
+
+ @retval 0 Write data failed.
+ @retval !0 Actual number of bytes written to serial device.
+
+**/
+UINTN
+EFIAPI
+SerialPortWrite (
+ IN UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+ )
+{
+ UINT64 SerialRegisterBase;
+
+ SerialRegisterBase = SerialPortGetBaseAddress ();
+ if (SerialRegisterBase != 0) {
+ return PL011UartWrite ((UINTN)SerialRegisterBase, Buffer, NumberOfBytes);
+ }
+ return 0;
+}
+
+/**
+ Read data from serial device and save the data in buffer.
+
+ @param Buffer Point of data buffer which need to be written.
+ @param NumberOfBytes Size of Buffer[].
+
+ @retval 0 Read data failed.
+ @retval !0 Actual number of bytes read from serial device.
+
+**/
+UINTN
+EFIAPI
+SerialPortRead (
+ OUT UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+)
+{
+ return 0;
+}
+
+/**
+ Check to see if any data is available to be read from the debug device.
+
+ @retval TRUE At least one byte of data is available to be read
+ @retval FALSE No data is available to be read
+
+**/
+BOOLEAN
+EFIAPI
+SerialPortPoll (
+ VOID
+ )
+{
+ return FALSE;
+}
diff --git a/ArmVirtPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.inf b/ArmVirtPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.inf
new file mode 100644
index 0000000000..fe892791b7
--- /dev/null
+++ b/ArmVirtPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.inf
@@ -0,0 +1,45 @@
+#/** @file
+#
+# Component description file for EarlyFdtPL011SerialPortLib module
+#
+# Copyright (c) 2011-2015, ARM Ltd. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = EarlyFdtPL011SerialPortLib
+ FILE_GUID = 0983616A-49BC-4732-B531-4AF98D2056F0
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SerialPortLib|SEC PEI_CORE PEIM
+
+[Sources.common]
+ EarlyFdtPL011SerialPortLib.c
+
+[LibraryClasses]
+ PL011UartLib
+ PcdLib
+ FdtLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ ArmVirtPkg/ArmVirtPkg.dec
+
+[FixedPcd]
+ gArmVirtTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress
+
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
diff --git a/ArmVirtPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.c b/ArmVirtPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.c
new file mode 100644
index 0000000000..aced6666a9
--- /dev/null
+++ b/ArmVirtPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.c
@@ -0,0 +1,150 @@
+/** @file
+ Serial I/O Port library functions with base address discovered from FDT
+
+ Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
+ Copyright (c) 2012 - 2013, ARM Ltd. All rights reserved.<BR>
+ Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR>
+ Copyright (c) 2014, Red Hat, Inc.<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/PcdLib.h>
+#include <Library/SerialPortLib.h>
+#include <Pi/PiBootMode.h>
+#include <Uefi/UefiBaseType.h>
+#include <Uefi/UefiMultiPhase.h>
+#include <Pi/PiHob.h>
+#include <Library/HobLib.h>
+#include <Guid/EarlyPL011BaseAddress.h>
+
+#include <Drivers/PL011Uart.h>
+
+STATIC UINTN mSerialBaseAddress;
+
+RETURN_STATUS
+EFIAPI
+SerialPortInitialize (
+ VOID
+ )
+{
+ return RETURN_SUCCESS;
+}
+
+/**
+
+ Program hardware of Serial port
+
+ @return RETURN_NOT_FOUND if no PL011 base address could be found
+ Otherwise, result of PL011UartInitializePort () is returned
+
+**/
+RETURN_STATUS
+EFIAPI
+FdtPL011SerialPortLibInitialize (
+ VOID
+ )
+{
+ VOID *Hob;
+ CONST UINT64 *UartBase;
+ UINT64 BaudRate;
+ UINT32 ReceiveFifoDepth;
+ EFI_PARITY_TYPE Parity;
+ UINT8 DataBits;
+ EFI_STOP_BITS_TYPE StopBits;
+
+ Hob = GetFirstGuidHob (&gEarlyPL011BaseAddressGuid);
+ if (Hob == NULL || GET_GUID_HOB_DATA_SIZE (Hob) != sizeof *UartBase) {
+ return RETURN_NOT_FOUND;
+ }
+ UartBase = GET_GUID_HOB_DATA (Hob);
+
+ mSerialBaseAddress = (UINTN)*UartBase;
+ if (mSerialBaseAddress == 0) {
+ return RETURN_NOT_FOUND;
+ }
+
+ BaudRate = (UINTN)PcdGet64 (PcdUartDefaultBaudRate);
+ ReceiveFifoDepth = 0; // Use the default value for Fifo depth
+ Parity = (EFI_PARITY_TYPE)PcdGet8 (PcdUartDefaultParity);
+ DataBits = PcdGet8 (PcdUartDefaultDataBits);
+ StopBits = (EFI_STOP_BITS_TYPE) PcdGet8 (PcdUartDefaultStopBits);
+
+ return PL011UartInitializePort (
+ mSerialBaseAddress, &BaudRate, &ReceiveFifoDepth,
+ &Parity, &DataBits, &StopBits);
+}
+
+/**
+ Write data to serial device.
+
+ @param Buffer Point of data buffer which need to be written.
+ @param NumberOfBytes Number of output bytes which are cached in Buffer.
+
+ @retval 0 Write data failed.
+ @retval !0 Actual number of bytes written to serial device.
+
+**/
+UINTN
+EFIAPI
+SerialPortWrite (
+ IN UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+ )
+{
+ if (mSerialBaseAddress != 0) {
+ return PL011UartWrite (mSerialBaseAddress, Buffer, NumberOfBytes);
+ }
+ return 0;
+}
+
+/**
+ Read data from serial device and save the data in buffer.
+
+ @param Buffer Point of data buffer which need to be written.
+ @param NumberOfBytes Number of output bytes which are cached in Buffer.
+
+ @retval 0 Read data failed.
+ @retval !0 Actual number of bytes read from serial device.
+
+**/
+UINTN
+EFIAPI
+SerialPortRead (
+ OUT UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+)
+{
+ if (mSerialBaseAddress != 0) {
+ return PL011UartRead (mSerialBaseAddress, Buffer, NumberOfBytes);
+ }
+ return 0;
+}
+
+/**
+ Check to see if any data is available to be read from the debug device.
+
+ @retval TRUE At least one byte of data is available to be read
+ @retval FALSE No data is available to be read
+
+**/
+BOOLEAN
+EFIAPI
+SerialPortPoll (
+ VOID
+ )
+{
+ if (mSerialBaseAddress != 0) {
+ return PL011UartPoll (mSerialBaseAddress);
+ }
+ return FALSE;
+}
diff --git a/ArmVirtPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.inf b/ArmVirtPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.inf
new file mode 100644
index 0000000000..3bacd641f0
--- /dev/null
+++ b/ArmVirtPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.inf
@@ -0,0 +1,48 @@
+#/** @file
+#
+# Component description file for PL011SerialPortLib module
+#
+# Copyright (c) 2011-2015, ARM Ltd. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FdtPL011SerialPortLib
+ FILE_GUID = CB768406-7DE6-49B6-BC2C-F324E110DE5A
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SerialPortLib|DXE_CORE DXE_DRIVER UEFI_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION
+ CONSTRUCTOR = FdtPL011SerialPortLibInitialize
+
+[Sources.common]
+ FdtPL011SerialPortLib.c
+
+[LibraryClasses]
+ PL011UartLib
+ HobLib
+
+[Packages]
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ ArmVirtPkg/ArmVirtPkg.dec
+ ArmPkg/ArmPkg.dec
+
+[FixedPcd]
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
+
+[Guids]
+ gEarlyPL011BaseAddressGuid
diff --git a/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c b/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c
new file mode 100644
index 0000000000..7f346077e6
--- /dev/null
+++ b/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c
@@ -0,0 +1,51 @@
+/** @file
+
+ 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 <ArmPlatform.h>
+#include <Library/NorFlashPlatformLib.h>
+
+EFI_STATUS
+NorFlashPlatformInitialization (
+ VOID
+ )
+{
+ return EFI_SUCCESS;
+}
+
+NOR_FLASH_DESCRIPTION mNorFlashDevices[] = {
+ {
+ QEMU_NOR0_BASE,
+ QEMU_NOR0_BASE,
+ QEMU_NOR0_SIZE,
+ QEMU_NOR_BLOCK_SIZE,
+ {0xF9B94AE2, 0x8BA6, 0x409B, {0x9D, 0x56, 0xB9, 0xB4, 0x17, 0xF5, 0x3C, 0xB3}}
+ }, {
+ QEMU_NOR1_BASE,
+ QEMU_NOR1_BASE,
+ QEMU_NOR1_SIZE,
+ QEMU_NOR_BLOCK_SIZE,
+ {0x8047DB4B, 0x7E9C, 0x4C0C, {0x8E, 0xBC, 0xDF, 0xBB, 0xAA, 0xCA, 0xCE, 0x8F}}
+ }
+};
+
+EFI_STATUS
+NorFlashPlatformGetDevices (
+ OUT NOR_FLASH_DESCRIPTION **NorFlashDescriptions,
+ OUT UINT32 *Count
+ )
+{
+ *NorFlashDescriptions = mNorFlashDevices;
+ *Count = sizeof (mNorFlashDevices) / sizeof (mNorFlashDevices[0]);
+ return EFI_SUCCESS;
+}
diff --git a/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf b/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf
new file mode 100644
index 0000000000..126d1671f5
--- /dev/null
+++ b/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf
@@ -0,0 +1,30 @@
+#/** @file
+#
+# Component description file for NorFlashQemuLib module
+#
+# 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 = NorFlashQemuLib
+ FILE_GUID = 339B7829-4C5F-4EFC-B2DD-5050E530DECE
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NorFlashPlatformLib
+
+[Sources.common]
+ NorFlashQemuLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
diff --git a/ArmVirtPkg/Library/PlatformIntelBdsLib/IntelBdsPlatform.c b/ArmVirtPkg/Library/PlatformIntelBdsLib/IntelBdsPlatform.c
new file mode 100644
index 0000000000..499cce5dcd
--- /dev/null
+++ b/ArmVirtPkg/Library/PlatformIntelBdsLib/IntelBdsPlatform.c
@@ -0,0 +1,477 @@
+/** @file
+ Implementation for PlatformBdsLib library class interfaces.
+
+ Copyright (C) 2015, Red Hat, Inc.
+ Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
+ Copyright (c) 2004 - 2008, Intel Corporation. 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 <IndustryStandard/Pci22.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PlatformBdsLib.h>
+#include <Library/QemuBootOrderLib.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/PciRootBridgeIo.h>
+
+#include "IntelBdsPlatform.h"
+
+#define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }
+
+
+#pragma pack (1)
+typedef struct {
+ VENDOR_DEVICE_PATH SerialDxe;
+ UART_DEVICE_PATH Uart;
+ VENDOR_DEFINED_DEVICE_PATH Vt100;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PLATFORM_SERIAL_CONSOLE;
+#pragma pack ()
+
+#define SERIAL_DXE_FILE_GUID { \
+ 0xD3987D4B, 0x971A, 0x435F, \
+ { 0x8C, 0xAF, 0x49, 0x67, 0xEB, 0x62, 0x72, 0x41 } \
+ }
+
+STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole = {
+ //
+ // VENDOR_DEVICE_PATH SerialDxe
+ //
+ {
+ { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) },
+ SERIAL_DXE_FILE_GUID
+ },
+
+ //
+ // UART_DEVICE_PATH Uart
+ //
+ {
+ { MESSAGING_DEVICE_PATH, MSG_UART_DP, DP_NODE_LEN (UART_DEVICE_PATH) },
+ 0, // Reserved
+ FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate
+ FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits
+ FixedPcdGet8 (PcdUartDefaultParity), // Parity
+ FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits
+ },
+
+ //
+ // VENDOR_DEFINED_DEVICE_PATH Vt100
+ //
+ {
+ {
+ MESSAGING_DEVICE_PATH, MSG_VENDOR_DP,
+ DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH)
+ },
+ EFI_VT_100_GUID
+ },
+
+ //
+ // EFI_DEVICE_PATH_PROTOCOL End
+ //
+ {
+ END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)
+ }
+};
+
+
+#pragma pack (1)
+typedef struct {
+ USB_CLASS_DEVICE_PATH Keyboard;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PLATFORM_USB_KEYBOARD;
+#pragma pack ()
+
+STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard = {
+ //
+ // USB_CLASS_DEVICE_PATH Keyboard
+ //
+ {
+ {
+ MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP,
+ DP_NODE_LEN (USB_CLASS_DEVICE_PATH)
+ },
+ 0xFFFF, // VendorId: any
+ 0xFFFF, // ProductId: any
+ 3, // DeviceClass: HID
+ 1, // DeviceSubClass: boot
+ 1 // DeviceProtocol: keyboard
+ },
+
+ //
+ // EFI_DEVICE_PATH_PROTOCOL End
+ //
+ {
+ END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)
+ }
+};
+
+
+//
+// BDS Platform Functions
+//
+/**
+ Platform Bds init. Include the platform firmware vendor, revision
+ and so crc check.
+
+**/
+VOID
+EFIAPI
+PlatformBdsInit (
+ VOID
+ )
+{
+}
+
+
+/**
+ Check if the handle satisfies a particular condition.
+
+ @param[in] Handle The handle to check.
+ @param[in] ReportText A caller-allocated string passed in for reporting
+ purposes. It must never be NULL.
+
+ @retval TRUE The condition is satisfied.
+ @retval FALSE Otherwise. This includes the case when the condition could not
+ be fully evaluated due to an error.
+**/
+typedef
+BOOLEAN
+(EFIAPI *FILTER_FUNCTION) (
+ IN EFI_HANDLE Handle,
+ IN CONST CHAR16 *ReportText
+ );
+
+
+/**
+ Process a handle.
+
+ @param[in] Handle The handle to process.
+ @param[in] ReportText A caller-allocated string passed in for reporting
+ purposes. It must never be NULL.
+**/
+typedef
+VOID
+(EFIAPI *CALLBACK_FUNCTION) (
+ IN EFI_HANDLE Handle,
+ IN CONST CHAR16 *ReportText
+ );
+
+/**
+ Locate all handles that carry the specified protocol, filter them with a
+ callback function, and pass each handle that passes the filter to another
+ callback.
+
+ @param[in] ProtocolGuid The protocol to look for.
+
+ @param[in] Filter The filter function to pass each handle to. If this
+ parameter is NULL, then all handles are processed.
+
+ @param[in] Process The callback function to pass each handle to that
+ clears the filter.
+**/
+STATIC
+VOID
+FilterAndProcess (
+ IN EFI_GUID *ProtocolGuid,
+ IN FILTER_FUNCTION Filter OPTIONAL,
+ IN CALLBACK_FUNCTION Process
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *Handles;
+ UINTN NoHandles;
+ UINTN Idx;
+
+ Status = gBS->LocateHandleBuffer (ByProtocol, ProtocolGuid,
+ NULL /* SearchKey */, &NoHandles, &Handles);
+ if (EFI_ERROR (Status)) {
+ //
+ // This is not an error, just an informative condition.
+ //
+ DEBUG ((EFI_D_VERBOSE, "%a: %g: %r\n", __FUNCTION__, ProtocolGuid,
+ Status));
+ return;
+ }
+
+ ASSERT (NoHandles > 0);
+ for (Idx = 0; Idx < NoHandles; ++Idx) {
+ CHAR16 *DevicePathText;
+ STATIC CHAR16 Fallback[] = L"<device path unavailable>";
+
+ //
+ // The ConvertDevicePathToText() function handles NULL input transparently.
+ //
+ DevicePathText = ConvertDevicePathToText (
+ DevicePathFromHandle (Handles[Idx]),
+ FALSE, // DisplayOnly
+ FALSE // AllowShortcuts
+ );
+ if (DevicePathText == NULL) {
+ DevicePathText = Fallback;
+ }
+
+ if (Filter == NULL || Filter (Handles[Idx], DevicePathText)) {
+ Process (Handles[Idx], DevicePathText);
+ }
+
+ if (DevicePathText != Fallback) {
+ FreePool (DevicePathText);
+ }
+ }
+ gBS->FreePool (Handles);
+}
+
+
+/**
+ This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.
+**/
+STATIC
+BOOLEAN
+EFIAPI
+IsPciDisplay (
+ IN EFI_HANDLE Handle,
+ IN CONST CHAR16 *ReportText
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+
+ Status = gBS->HandleProtocol (Handle, &gEfiPciIoProtocolGuid,
+ (VOID**)&PciIo);
+ if (EFI_ERROR (Status)) {
+ //
+ // This is not an error worth reporting.
+ //
+ return FALSE;
+ }
+
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0 /* Offset */,
+ sizeof Pci / sizeof (UINT32), &Pci);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a: %s: %r\n", __FUNCTION__, ReportText, Status));
+ return FALSE;
+ }
+
+ return IS_PCI_DISPLAY (&Pci);
+}
+
+
+/**
+ This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking
+ the matching driver to produce all first-level child handles.
+**/
+STATIC
+VOID
+EFIAPI
+Connect (
+ IN EFI_HANDLE Handle,
+ IN CONST CHAR16 *ReportText
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->ConnectController (
+ Handle, // ControllerHandle
+ NULL, // DriverImageHandle
+ NULL, // RemainingDevicePath -- produce all children
+ FALSE // Recursive
+ );
+ DEBUG ((EFI_ERROR (Status) ? EFI_D_ERROR : EFI_D_VERBOSE, "%a: %s: %r\n",
+ __FUNCTION__, ReportText, Status));
+}
+
+
+/**
+ This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the
+ handle, and adds it to ConOut and ErrOut.
+**/
+STATIC
+VOID
+EFIAPI
+AddOutput (
+ IN EFI_HANDLE Handle,
+ IN CONST CHAR16 *ReportText
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ DevicePath = DevicePathFromHandle (Handle);
+ if (DevicePath == NULL) {
+ DEBUG ((EFI_D_ERROR, "%a: %s: handle %p: device path not found\n",
+ __FUNCTION__, ReportText, Handle));
+ return;
+ }
+
+ Status = BdsLibUpdateConsoleVariable (L"ConOut", DevicePath, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a: %s: adding to ConOut: %r\n", __FUNCTION__,
+ ReportText, Status));
+ return;
+ }
+
+ Status = BdsLibUpdateConsoleVariable (L"ErrOut", DevicePath, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__,
+ ReportText, Status));
+ return;
+ }
+
+ DEBUG ((EFI_D_VERBOSE, "%a: %s: added to ConOut and ErrOut\n", __FUNCTION__,
+ ReportText));
+}
+
+
+/**
+ The function will execute with as the platform policy, current policy
+ is driven by boot mode. IBV/OEM can customize this code for their specific
+ policy action.
+
+ @param DriverOptionList The header of the driver option link list
+ @param BootOptionList The header of the boot option link list
+ @param ProcessCapsules A pointer to ProcessCapsules()
+ @param BaseMemoryTest A pointer to BaseMemoryTest()
+
+**/
+VOID
+EFIAPI
+PlatformBdsPolicyBehavior (
+ IN LIST_ENTRY *DriverOptionList,
+ IN LIST_ENTRY *BootOptionList,
+ IN PROCESS_CAPSULES ProcessCapsules,
+ IN BASEM_MEMORY_TEST BaseMemoryTest
+ )
+{
+ //
+ // Locate the PCI root bridges and make the PCI bus driver connect each,
+ // non-recursively. This will produce a number of child handles with PciIo on
+ // them.
+ //
+ FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect);
+
+ //
+ // Find all display class PCI devices (using the handles from the previous
+ // step), and connect them non-recursively. This should produce a number of
+ // child handles with GOPs on them.
+ //
+ FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect);
+
+ //
+ // Now add the device path of all handles with GOP on them to ConOut and
+ // ErrOut.
+ //
+ FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput);
+
+ //
+ // Add the hardcoded short-form USB keyboard device path to ConIn.
+ //
+ BdsLibUpdateConsoleVariable (L"ConIn",
+ (EFI_DEVICE_PATH_PROTOCOL *)&mUsbKeyboard, NULL);
+
+ //
+ // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut.
+ //
+ BdsLibUpdateConsoleVariable (L"ConIn",
+ (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);
+ BdsLibUpdateConsoleVariable (L"ConOut",
+ (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);
+ BdsLibUpdateConsoleVariable (L"ErrOut",
+ (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);
+
+ //
+ // Connect the consoles based on the above variables.
+ //
+ BdsLibConnectAllDefaultConsoles ();
+
+ //
+ // Show the splash screen.
+ //
+ EnableQuietBoot (PcdGetPtr (PcdLogoFile));
+
+ //
+ // Connect the rest of the devices.
+ //
+ BdsLibConnectAll ();
+
+ //
+ // Process QEMU's -kernel command line option. Note that the kernel booted
+ // this way should receive ACPI tables, which is why we connect all devices
+ // first (see above) -- PCI enumeration blocks ACPI table installation, if
+ // there is a PCI host.
+ //
+ TryRunningQemuKernel ();
+
+ BdsLibEnumerateAllBootOption (BootOptionList);
+ SetBootOrderFromQemu (BootOptionList);
+ //
+ // The BootOrder variable may have changed, reload the in-memory list with
+ // it.
+ //
+ BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
+
+ PlatformBdsEnterFrontPage (GetFrontPageTimeoutFromQemu(), TRUE);
+}
+
+/**
+ Hook point after a boot attempt succeeds. We don't expect a boot option to
+ return, so the UEFI 2.0 specification defines that you will default to an
+ interactive mode and stop processing the BootOrder list in this case. This
+ is also a platform implementation and can be customized by IBV/OEM.
+
+ @param Option Pointer to Boot Option that succeeded to boot.
+
+**/
+VOID
+EFIAPI
+PlatformBdsBootSuccess (
+ IN BDS_COMMON_OPTION *Option
+ )
+{
+}
+
+/**
+ Hook point after a boot attempt fails.
+
+ @param Option Pointer to Boot Option that failed to boot.
+ @param Status Status returned from failed boot.
+ @param ExitData Exit data returned from failed boot.
+ @param ExitDataSize Exit data size returned from failed boot.
+
+**/
+VOID
+EFIAPI
+PlatformBdsBootFail (
+ IN BDS_COMMON_OPTION *Option,
+ IN EFI_STATUS Status,
+ IN CHAR16 *ExitData,
+ IN UINTN ExitDataSize
+ )
+{
+}
+
+/**
+ This function locks platform flash that is not allowed to be updated during normal boot path.
+ The flash layout is platform specific.
+**/
+VOID
+EFIAPI
+PlatformBdsLockNonUpdatableFlash (
+ VOID
+ )
+{
+ return;
+}
diff --git a/ArmVirtPkg/Library/PlatformIntelBdsLib/IntelBdsPlatform.h b/ArmVirtPkg/Library/PlatformIntelBdsLib/IntelBdsPlatform.h
new file mode 100644
index 0000000000..3d29b0d099
--- /dev/null
+++ b/ArmVirtPkg/Library/PlatformIntelBdsLib/IntelBdsPlatform.h
@@ -0,0 +1,55 @@
+/** @file
+ Head file for BDS Platform specific code
+
+ Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _INTEL_BDS_PLATFORM_H_
+#define _INTEL_BDS_PLATFORM_H_
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+VOID
+PlatformBdsEnterFrontPage (
+ IN UINT16 TimeoutDefault,
+ IN BOOLEAN ConnectAllHappened
+ );
+
+/**
+ Download the kernel, the initial ramdisk, and the kernel command line from
+ QEMU's fw_cfg. Construct a minimal SimpleFileSystem that contains the two
+ image files, and load and start the kernel from it.
+
+ The kernel will be instructed via its command line to load the initrd from
+ the same Simple FileSystem.
+
+ @retval EFI_NOT_FOUND Kernel image was not found.
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
+ @retval EFI_PROTOCOL_ERROR Unterminated kernel command line.
+
+ @return Error codes from any of the underlying
+ functions. On success, the function doesn't
+ return.
+**/
+EFI_STATUS
+EFIAPI
+TryRunningQemuKernel (
+ VOID
+ );
+
+#endif // _INTEL_BDS_PLATFORM_H
diff --git a/ArmVirtPkg/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf b/ArmVirtPkg/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf
new file mode 100644
index 0000000000..d8f892642c
--- /dev/null
+++ b/ArmVirtPkg/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf
@@ -0,0 +1,74 @@
+## @file
+# Implementation for PlatformBdsLib library class interfaces.
+#
+# Copyright (C) 2015, Red Hat, Inc.
+# Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
+# Copyright (c) 2007 - 2014, Intel Corporation. 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 = PlatformIntelBdsLib
+ FILE_GUID = 46DF84EB-F603-4D39-99D8-E1E86B50BCC2
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformBdsLib|DXE_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = ARM AARCH64
+#
+
+[Sources]
+ IntelBdsPlatform.c
+ QemuKernel.c
+
+[Packages]
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ DevicePathLib
+ GenericBdsLib
+ MemoryAllocationLib
+ PcdLib
+ PrintLib
+ QemuBootOrderLib
+ QemuFwCfgLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+
+[FixedPcd]
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLogoFile
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
+
+[Guids]
+ gEfiFileInfoGuid
+ gEfiFileSystemInfoGuid
+ gEfiFileSystemVolumeLabelInfoIdGuid
+
+[Protocols]
+ gEfiDevicePathProtocolGuid
+ gEfiGraphicsOutputProtocolGuid
+ gEfiLoadedImageProtocolGuid
+ gEfiPciRootBridgeIoProtocolGuid
+ gEfiSimpleFileSystemProtocolGuid
diff --git a/ArmVirtPkg/Library/PlatformIntelBdsLib/QemuKernel.c b/ArmVirtPkg/Library/PlatformIntelBdsLib/QemuKernel.c
new file mode 100644
index 0000000000..21545f066e
--- /dev/null
+++ b/ArmVirtPkg/Library/PlatformIntelBdsLib/QemuKernel.c
@@ -0,0 +1,1108 @@
+/** @file
+ Try to load an EFI-stubbed ARM Linux kernel from QEMU's fw_cfg.
+
+ This implementation differs from OvmfPkg/Library/LoadLinuxLib. An EFI
+ stub in the subject kernel is a hard requirement here.
+
+ Copyright (C) 2014, Red Hat, Inc.
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Guid/FileInfo.h>
+#include <Guid/FileSystemInfo.h>
+#include <Guid/FileSystemVolumeLabelInfo.h>
+#include <Library/PrintLib.h>
+#include <Library/QemuFwCfgLib.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/SimpleFileSystem.h>
+
+#include "IntelBdsPlatform.h"
+
+//
+// Static data that hosts the fw_cfg blobs and serves file requests.
+//
+typedef enum {
+ KernelBlobTypeKernel,
+ KernelBlobTypeInitrd,
+ KernelBlobTypeCommandLine,
+ KernelBlobTypeMax
+} KERNEL_BLOB_TYPE;
+
+typedef struct {
+ FIRMWARE_CONFIG_ITEM CONST SizeKey;
+ FIRMWARE_CONFIG_ITEM CONST DataKey;
+ CONST CHAR16 * CONST Name;
+ UINT32 Size;
+ UINT8 *Data;
+} KERNEL_BLOB;
+
+STATIC KERNEL_BLOB mKernelBlob[KernelBlobTypeMax] = {
+ { QemuFwCfgItemKernelSize, QemuFwCfgItemKernelData, L"kernel" },
+ { QemuFwCfgItemInitrdSize, QemuFwCfgItemInitrdData, L"initrd" },
+ { QemuFwCfgItemCommandLineSize, QemuFwCfgItemCommandLineData, L"cmdline" }
+};
+
+STATIC UINT64 mTotalBlobBytes;
+
+//
+// Device path for the handle that incorporates our "EFI stub filesystem". The
+// GUID is arbitrary and need not be standardized or advertized.
+//
+#pragma pack(1)
+typedef struct {
+ VENDOR_DEVICE_PATH VenHwNode;
+ EFI_DEVICE_PATH_PROTOCOL EndNode;
+} SINGLE_VENHW_NODE_DEVPATH;
+#pragma pack()
+
+STATIC CONST SINGLE_VENHW_NODE_DEVPATH mFileSystemDevicePath = {
+ {
+ { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, { sizeof (VENDOR_DEVICE_PATH) } },
+ {
+ 0xb0fae7e7, 0x6b07, 0x49d0,
+ { 0x9e, 0x5b, 0x3b, 0xde, 0xc8, 0x3b, 0x03, 0x9d }
+ }
+ },
+
+ {
+ END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ { sizeof (EFI_DEVICE_PATH_PROTOCOL) }
+ }
+};
+
+//
+// The "file in the EFI stub filesystem" abstraction.
+//
+STATIC EFI_TIME mInitTime;
+
+#define STUB_FILE_SIG SIGNATURE_64 ('S', 'T', 'U', 'B', 'F', 'I', 'L', 'E')
+
+typedef struct {
+ UINT64 Signature; // Carries STUB_FILE_SIG.
+
+ KERNEL_BLOB_TYPE BlobType; // Index into mKernelBlob. KernelBlobTypeMax
+ // denotes the root directory of the filesystem.
+
+ UINT64 Position; // Byte position for regular files;
+ // next directory entry to return for the root
+ // directory.
+
+ EFI_FILE_PROTOCOL File; // Standard protocol interface.
+} STUB_FILE;
+
+#define STUB_FILE_FROM_FILE(FilePointer) \
+ CR (FilePointer, STUB_FILE, File, STUB_FILE_SIG)
+
+//
+// Tentative definition of the file protocol template. The initializer
+// (external definition) will be provided later.
+//
+STATIC CONST EFI_FILE_PROTOCOL mEfiFileProtocolTemplate;
+
+
+//
+// Protocol member functions for File.
+//
+
+/**
+ Opens a new file relative to the source file's location.
+
+ @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is
+ the file handle to the source location. This would
+ typically be an open handle to a directory.
+
+ @param[out] NewHandle A pointer to the location to return the opened handle
+ for the new file.
+
+ @param[in] FileName The Null-terminated string of the name of the file to
+ be opened. The file name may contain the following
+ path modifiers: "\", ".", and "..".
+
+ @param[in] OpenMode The mode to open the file. The only valid
+ combinations that the file may be opened with are:
+ Read, Read/Write, or Create/Read/Write.
+
+ @param[in] Attributes Only valid for EFI_FILE_MODE_CREATE, in which case
+ these are the attribute bits for the newly created
+ file.
+
+ @retval EFI_SUCCESS The file was opened.
+ @retval EFI_NOT_FOUND The specified file could not be found on the
+ device.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_MEDIA_CHANGED The device has a different medium in it or the
+ medium is no longer supported.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a
+ file for write when the media is
+ write-protected.
+ @retval EFI_ACCESS_DENIED The service denied access to the file.
+ @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the
+ file.
+ @retval EFI_VOLUME_FULL The volume is full.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+StubFileOpen (
+ IN EFI_FILE_PROTOCOL *This,
+ OUT EFI_FILE_PROTOCOL **NewHandle,
+ IN CHAR16 *FileName,
+ IN UINT64 OpenMode,
+ IN UINT64 Attributes
+ )
+{
+ CONST STUB_FILE *StubFile;
+ UINTN BlobType;
+ STUB_FILE *NewStubFile;
+
+ //
+ // We're read-only.
+ //
+ switch (OpenMode) {
+ case EFI_FILE_MODE_READ:
+ break;
+
+ case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:
+ case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE:
+ return EFI_WRITE_PROTECTED;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Only the root directory supports opening files in it.
+ //
+ StubFile = STUB_FILE_FROM_FILE (This);
+ if (StubFile->BlobType != KernelBlobTypeMax) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Locate the file.
+ //
+ for (BlobType = 0; BlobType < KernelBlobTypeMax; ++BlobType) {
+ if (StrCmp (FileName, mKernelBlob[BlobType].Name) == 0) {
+ break;
+ }
+ }
+ if (BlobType == KernelBlobTypeMax) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Found it.
+ //
+ NewStubFile = AllocatePool (sizeof *NewStubFile);
+ if (NewStubFile == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewStubFile->Signature = STUB_FILE_SIG;
+ NewStubFile->BlobType = (KERNEL_BLOB_TYPE)BlobType;
+ NewStubFile->Position = 0;
+ CopyMem (&NewStubFile->File, &mEfiFileProtocolTemplate,
+ sizeof mEfiFileProtocolTemplate);
+ *NewHandle = &NewStubFile->File;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Closes a specified file handle.
+
+ @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the file
+ handle to close.
+
+ @retval EFI_SUCCESS The file was closed.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+StubFileClose (
+ IN EFI_FILE_PROTOCOL *This
+ )
+{
+ FreePool (STUB_FILE_FROM_FILE (This));
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Close and delete the file handle.
+
+ @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the
+ handle to the file to delete.
+
+ @retval EFI_SUCCESS The file was closed and deleted, and the
+ handle was closed.
+ @retval EFI_WARN_DELETE_FAILURE The handle was closed, but the file was not
+ deleted.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+StubFileDelete (
+ IN EFI_FILE_PROTOCOL *This
+ )
+{
+ FreePool (STUB_FILE_FROM_FILE (This));
+ return EFI_WARN_DELETE_FAILURE;
+}
+
+
+/**
+ Helper function that formats an EFI_FILE_INFO structure into the
+ user-allocated buffer, for any valid KERNEL_BLOB_TYPE value (including
+ KernelBlobTypeMax, which stands for the root directory).
+
+ The interface follows the EFI_FILE_GET_INFO -- and for directories, the
+ EFI_FILE_READ -- interfaces.
+
+ @param[in] BlobType The KERNEL_BLOB_TYPE value identifying the fw_cfg
+ blob backing the STUB_FILE that information is
+ being requested about. If BlobType equals
+ KernelBlobTypeMax, then information will be
+ provided about the root directory of the
+ filesystem.
+
+ @param[in,out] BufferSize On input, the size of Buffer. On output, the
+ amount of data returned in Buffer. In both cases,
+ the size is measured in bytes.
+
+ @param[out] Buffer A pointer to the data buffer to return. The
+ buffer's type is EFI_FILE_INFO.
+
+ @retval EFI_SUCCESS The information was returned.
+ @retval EFI_BUFFER_TOO_SMALL BufferSize is too small to store the
+ EFI_FILE_INFO structure. BufferSize has been
+ updated with the size needed to complete the
+ request.
+**/
+STATIC
+EFI_STATUS
+ConvertKernelBlobTypeToFileInfo (
+ IN KERNEL_BLOB_TYPE BlobType,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ CONST CHAR16 *Name;
+ UINT64 FileSize;
+ UINT64 Attribute;
+
+ UINTN NameSize;
+ UINTN FileInfoSize;
+ EFI_FILE_INFO *FileInfo;
+ UINTN OriginalBufferSize;
+
+ if (BlobType == KernelBlobTypeMax) {
+ //
+ // getting file info about the root directory
+ //
+ Name = L"\\";
+ FileSize = KernelBlobTypeMax;
+ Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY;
+ } else {
+ CONST KERNEL_BLOB *Blob;
+
+ Blob = &mKernelBlob[BlobType];
+ Name = Blob->Name;
+ FileSize = Blob->Size;
+ Attribute = EFI_FILE_READ_ONLY;
+ }
+
+ NameSize = (StrLen(Name) + 1) * 2;
+ FileInfoSize = OFFSET_OF (EFI_FILE_INFO, FileName) + NameSize;
+ ASSERT (FileInfoSize >= sizeof *FileInfo);
+
+ OriginalBufferSize = *BufferSize;
+ *BufferSize = FileInfoSize;
+ if (OriginalBufferSize < *BufferSize) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ FileInfo = (EFI_FILE_INFO *)Buffer;
+ FileInfo->Size = FileInfoSize;
+ FileInfo->FileSize = FileSize;
+ FileInfo->PhysicalSize = FileSize;
+ FileInfo->Attribute = Attribute;
+
+ CopyMem (&FileInfo->CreateTime, &mInitTime, sizeof mInitTime);
+ CopyMem (&FileInfo->LastAccessTime, &mInitTime, sizeof mInitTime);
+ CopyMem (&FileInfo->ModificationTime, &mInitTime, sizeof mInitTime);
+ CopyMem (FileInfo->FileName, Name, NameSize);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Reads data from a file, or continues scanning a directory.
+
+ @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that
+ is the file handle to read data from.
+
+ @param[in,out] BufferSize On input, the size of the Buffer. On output, the
+ amount of data returned in Buffer. In both cases,
+ the size is measured in bytes. If the read goes
+ beyond the end of the file, the read length is
+ truncated to the end of the file.
+
+ If This is a directory, the function reads the
+ directory entry at the current position and
+ returns the entry (as EFI_FILE_INFO) in Buffer. If
+ there are no more directory entries, the
+ BufferSize is set to zero on output.
+
+ @param[out] Buffer The buffer into which the data is read.
+
+ @retval EFI_SUCCESS Data was read.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_DEVICE_ERROR An attempt was made to read from a deleted
+ file.
+ @retval EFI_DEVICE_ERROR On entry, the current file position is beyond
+ the end of the file.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to store the
+ current directory entry as a EFI_FILE_INFO
+ structure. BufferSize has been updated with the
+ size needed to complete the request, and the
+ directory position has not been advanced.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+StubFileRead (
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ STUB_FILE *StubFile;
+ CONST KERNEL_BLOB *Blob;
+ UINT64 Left;
+
+ StubFile = STUB_FILE_FROM_FILE (This);
+
+ //
+ // Scanning the root directory?
+ //
+ if (StubFile->BlobType == KernelBlobTypeMax) {
+ EFI_STATUS Status;
+
+ if (StubFile->Position == KernelBlobTypeMax) {
+ //
+ // Scanning complete.
+ //
+ *BufferSize = 0;
+ return EFI_SUCCESS;
+ }
+
+ Status = ConvertKernelBlobTypeToFileInfo (StubFile->Position, BufferSize,
+ Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ++StubFile->Position;
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Reading a file.
+ //
+ Blob = &mKernelBlob[StubFile->BlobType];
+ if (StubFile->Position > Blob->Size) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Left = Blob->Size - StubFile->Position;
+ if (*BufferSize > Left) {
+ *BufferSize = (UINTN)Left;
+ }
+ if (Blob->Data != NULL) {
+ CopyMem (Buffer, Blob->Data + StubFile->Position, *BufferSize);
+ }
+ StubFile->Position += *BufferSize;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Writes data to a file.
+
+ @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that
+ is the file handle to write data to.
+
+ @param[in,out] BufferSize On input, the size of the Buffer. On output, the
+ amount of data actually written. In both cases,
+ the size is measured in bytes.
+
+ @param[in] Buffer The buffer of data to write.
+
+ @retval EFI_SUCCESS Data was written.
+ @retval EFI_UNSUPPORTED Writes to open directory files are not
+ supported.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_DEVICE_ERROR An attempt was made to write to a deleted file.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The file or medium is write-protected.
+ @retval EFI_ACCESS_DENIED The file was opened read only.
+ @retval EFI_VOLUME_FULL The volume is full.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+StubFileWrite (
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ )
+{
+ STUB_FILE *StubFile;
+
+ StubFile = STUB_FILE_FROM_FILE (This);
+ return (StubFile->BlobType == KernelBlobTypeMax) ?
+ EFI_UNSUPPORTED :
+ EFI_WRITE_PROTECTED;
+}
+
+
+/**
+ Returns a file's current position.
+
+ @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the
+ file handle to get the current position on.
+
+ @param[out] Position The address to return the file's current position
+ value.
+
+ @retval EFI_SUCCESS The position was returned.
+ @retval EFI_UNSUPPORTED The request is not valid on open directories.
+ @retval EFI_DEVICE_ERROR An attempt was made to get the position from a
+ deleted file.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+StubFileGetPosition (
+ IN EFI_FILE_PROTOCOL *This,
+ OUT UINT64 *Position
+ )
+{
+ STUB_FILE *StubFile;
+
+ StubFile = STUB_FILE_FROM_FILE (This);
+ if (StubFile->BlobType == KernelBlobTypeMax) {
+ return EFI_UNSUPPORTED;
+ }
+
+ *Position = StubFile->Position;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Sets a file's current position.
+
+ @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the
+ file handle to set the requested position on.
+
+ @param[in] Position The byte position from the start of the file to set. For
+ regular files, MAX_UINT64 means "seek to end". For
+ directories, zero means "rewind directory scan".
+
+ @retval EFI_SUCCESS The position was set.
+ @retval EFI_UNSUPPORTED The seek request for nonzero is not valid on open
+ directories.
+ @retval EFI_DEVICE_ERROR An attempt was made to set the position of a
+ deleted file.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+StubFileSetPosition (
+ IN EFI_FILE_PROTOCOL *This,
+ IN UINT64 Position
+ )
+{
+ STUB_FILE *StubFile;
+ KERNEL_BLOB *Blob;
+
+ StubFile = STUB_FILE_FROM_FILE (This);
+
+ if (StubFile->BlobType == KernelBlobTypeMax) {
+ if (Position == 0) {
+ //
+ // rewinding a directory scan is allowed
+ //
+ StubFile->Position = 0;
+ return EFI_SUCCESS;
+ }
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // regular file seek
+ //
+ Blob = &mKernelBlob[StubFile->BlobType];
+ if (Position == MAX_UINT64) {
+ //
+ // seek to end
+ //
+ StubFile->Position = Blob->Size;
+ } else {
+ //
+ // absolute seek from beginning -- seeking past the end is allowed
+ //
+ StubFile->Position = Position;
+ }
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Returns information about a file.
+
+ @param[in] This A pointer to the EFI_FILE_PROTOCOL instance
+ that is the file handle the requested
+ information is for.
+
+ @param[in] InformationType The type identifier GUID for the information
+ being requested. The following information
+ types are supported, storing the
+ corresponding structures in Buffer:
+
+ - gEfiFileInfoGuid: EFI_FILE_INFO
+
+ - gEfiFileSystemInfoGuid:
+ EFI_FILE_SYSTEM_INFO
+
+ - gEfiFileSystemVolumeLabelInfoIdGuid:
+ EFI_FILE_SYSTEM_VOLUME_LABEL
+
+ @param[in,out] BufferSize On input, the size of Buffer. On output, the
+ amount of data returned in Buffer. In both
+ cases, the size is measured in bytes.
+
+ @param[out] Buffer A pointer to the data buffer to return. The
+ buffer's type is indicated by
+ InformationType.
+
+ @retval EFI_SUCCESS The information was returned.
+ @retval EFI_UNSUPPORTED The InformationType is not known.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to store the
+ information structure requested by
+ InformationType. BufferSize has been updated
+ with the size needed to complete the request.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+StubFileGetInfo (
+ IN EFI_FILE_PROTOCOL *This,
+ IN EFI_GUID *InformationType,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ CONST STUB_FILE *StubFile;
+ UINTN OriginalBufferSize;
+
+ StubFile = STUB_FILE_FROM_FILE (This);
+
+ if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
+ return ConvertKernelBlobTypeToFileInfo (StubFile->BlobType, BufferSize,
+ Buffer);
+ }
+
+ OriginalBufferSize = *BufferSize;
+
+ if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
+ EFI_FILE_SYSTEM_INFO *FileSystemInfo;
+
+ *BufferSize = sizeof *FileSystemInfo;
+ if (OriginalBufferSize < *BufferSize) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ FileSystemInfo = (EFI_FILE_SYSTEM_INFO *)Buffer;
+ FileSystemInfo->Size = sizeof *FileSystemInfo;
+ FileSystemInfo->ReadOnly = TRUE;
+ FileSystemInfo->VolumeSize = mTotalBlobBytes;
+ FileSystemInfo->FreeSpace = 0;
+ FileSystemInfo->BlockSize = 1;
+ FileSystemInfo->VolumeLabel[0] = L'\0';
+
+ return EFI_SUCCESS;
+ }
+
+ if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
+ EFI_FILE_SYSTEM_VOLUME_LABEL *FileSystemVolumeLabel;
+
+ *BufferSize = sizeof *FileSystemVolumeLabel;
+ if (OriginalBufferSize < *BufferSize) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ FileSystemVolumeLabel = (EFI_FILE_SYSTEM_VOLUME_LABEL *)Buffer;
+ FileSystemVolumeLabel->VolumeLabel[0] = L'\0';
+
+ return EFI_SUCCESS;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ Sets information about a file.
+
+ @param[in] File A pointer to the EFI_FILE_PROTOCOL instance that
+ is the file handle the information is for.
+
+ @param[in] InformationType The type identifier for the information being
+ set.
+
+ @param[in] BufferSize The size, in bytes, of Buffer.
+
+ @param[in] Buffer A pointer to the data buffer to write. The
+ buffer's type is indicated by InformationType.
+
+ @retval EFI_SUCCESS The information was set.
+ @retval EFI_UNSUPPORTED The InformationType is not known.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED InformationType is EFI_FILE_INFO_ID and the
+ media is read-only.
+ @retval EFI_WRITE_PROTECTED InformationType is
+ EFI_FILE_PROTOCOL_SYSTEM_INFO_ID and the media
+ is read only.
+ @retval EFI_WRITE_PROTECTED InformationType is
+ EFI_FILE_SYSTEM_VOLUME_LABEL_ID and the media
+ is read-only.
+ @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file
+ to a file that is already present.
+ @retval EFI_ACCESS_DENIED An attempt is being made to change the
+ EFI_FILE_DIRECTORY Attribute.
+ @retval EFI_ACCESS_DENIED An attempt is being made to change the size of
+ a directory.
+ @retval EFI_ACCESS_DENIED InformationType is EFI_FILE_INFO_ID and the
+ file was opened read-only and an attempt is
+ being made to modify a field other than
+ Attribute.
+ @retval EFI_VOLUME_FULL The volume is full.
+ @retval EFI_BAD_BUFFER_SIZE BufferSize is smaller than the size of the type
+ indicated by InformationType.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+StubFileSetInfo (
+ IN EFI_FILE_PROTOCOL *This,
+ IN EFI_GUID *InformationType,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ return EFI_WRITE_PROTECTED;
+}
+
+
+/**
+ Flushes all modified data associated with a file to a device.
+
+ @param [in] This A pointer to the EFI_FILE_PROTOCOL instance that is the
+ file handle to flush.
+
+ @retval EFI_SUCCESS The data was flushed.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The file or medium is write-protected.
+ @retval EFI_ACCESS_DENIED The file was opened read-only.
+ @retval EFI_VOLUME_FULL The volume is full.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+StubFileFlush (
+ IN EFI_FILE_PROTOCOL *This
+ )
+{
+ return EFI_WRITE_PROTECTED;
+}
+
+//
+// External definition of the file protocol template.
+//
+STATIC CONST EFI_FILE_PROTOCOL mEfiFileProtocolTemplate = {
+ EFI_FILE_PROTOCOL_REVISION, // revision 1
+ StubFileOpen,
+ StubFileClose,
+ StubFileDelete,
+ StubFileRead,
+ StubFileWrite,
+ StubFileGetPosition,
+ StubFileSetPosition,
+ StubFileGetInfo,
+ StubFileSetInfo,
+ StubFileFlush,
+ NULL, // OpenEx, revision 2
+ NULL, // ReadEx, revision 2
+ NULL, // WriteEx, revision 2
+ NULL // FlushEx, revision 2
+};
+
+
+//
+// Protocol member functions for SimpleFileSystem.
+//
+
+/**
+ Open the root directory on a volume.
+
+ @param[in] This A pointer to the volume to open the root directory on.
+
+ @param[out] Root A pointer to the location to return the opened file handle
+ for the root directory in.
+
+ @retval EFI_SUCCESS The device was opened.
+ @retval EFI_UNSUPPORTED This volume does not support the requested file
+ system type.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_ACCESS_DENIED The service denied access to the file.
+ @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of
+ resources.
+ @retval EFI_MEDIA_CHANGED The device has a different medium in it or the
+ medium is no longer supported. Any existing
+ file handles for this volume are no longer
+ valid. To access the files on the new medium,
+ the volume must be reopened with OpenVolume().
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+StubFileSystemOpenVolume (
+ IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
+ OUT EFI_FILE_PROTOCOL **Root
+ )
+{
+ STUB_FILE *StubFile;
+
+ StubFile = AllocatePool (sizeof *StubFile);
+ if (StubFile == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StubFile->Signature = STUB_FILE_SIG;
+ StubFile->BlobType = KernelBlobTypeMax;
+ StubFile->Position = 0;
+ CopyMem (&StubFile->File, &mEfiFileProtocolTemplate,
+ sizeof mEfiFileProtocolTemplate);
+ *Root = &StubFile->File;
+
+ return EFI_SUCCESS;
+}
+
+STATIC CONST EFI_SIMPLE_FILE_SYSTEM_PROTOCOL mFileSystem = {
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION,
+ StubFileSystemOpenVolume
+};
+
+
+//
+// Utility functions.
+//
+
+/**
+ Populate a blob in mKernelBlob.
+
+ param[in,out] Blob Pointer to the KERNEL_BLOB element in mKernelBlob that is
+ to be filled from fw_cfg.
+
+ @retval EFI_SUCCESS Blob has been populated. If fw_cfg reported a
+ size of zero for the blob, then Blob->Data has
+ been left unchanged.
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory for Blob->Data.
+**/
+STATIC
+EFI_STATUS
+FetchBlob (
+ IN OUT KERNEL_BLOB *Blob
+ )
+{
+ UINT32 Left;
+
+ //
+ // Read blob size.
+ //
+ QemuFwCfgSelectItem (Blob->SizeKey);
+ Blob->Size = QemuFwCfgRead32 ();
+ if (Blob->Size == 0) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Read blob.
+ //
+ Blob->Data = AllocatePool (Blob->Size);
+ if (Blob->Data == NULL) {
+ DEBUG ((EFI_D_ERROR, "%a: failed to allocate %Ld bytes for \"%s\"\n",
+ __FUNCTION__, (INT64)Blob->Size, Blob->Name));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ DEBUG ((EFI_D_INFO, "%a: loading %Ld bytes for \"%s\"\n", __FUNCTION__,
+ (INT64)Blob->Size, Blob->Name));
+ QemuFwCfgSelectItem (Blob->DataKey);
+
+ Left = Blob->Size;
+ do {
+ UINT32 Chunk;
+
+ Chunk = (Left < SIZE_1MB) ? Left : SIZE_1MB;
+ QemuFwCfgReadBytes (Chunk, Blob->Data + (Blob->Size - Left));
+ Left -= Chunk;
+ DEBUG ((EFI_D_VERBOSE, "%a: %Ld bytes remaining for \"%s\"\n",
+ __FUNCTION__, (INT64)Left, Blob->Name));
+ } while (Left > 0);
+ return EFI_SUCCESS;
+}
+
+
+//
+// The entry point of the feature.
+//
+
+/**
+ Download the kernel, the initial ramdisk, and the kernel command line from
+ QEMU's fw_cfg. Construct a minimal SimpleFileSystem that contains the two
+ image files, and load and start the kernel from it.
+
+ The kernel will be instructed via its command line to load the initrd from
+ the same Simple FileSystem.
+
+ @retval EFI_NOT_FOUND Kernel image was not found.
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
+ @retval EFI_PROTOCOL_ERROR Unterminated kernel command line.
+
+ @return Error codes from any of the underlying
+ functions. On success, the function doesn't
+ return.
+**/
+EFI_STATUS
+EFIAPI
+TryRunningQemuKernel (
+ VOID
+ )
+{
+ UINTN BlobType;
+ KERNEL_BLOB *CurrentBlob;
+ KERNEL_BLOB *KernelBlob, *InitrdBlob, *CommandLineBlob;
+ EFI_STATUS Status;
+ EFI_HANDLE FileSystemHandle;
+ EFI_DEVICE_PATH_PROTOCOL *KernelDevicePath;
+ EFI_HANDLE KernelImageHandle;
+ EFI_LOADED_IMAGE_PROTOCOL *KernelLoadedImage;
+
+ Status = gRT->GetTime (&mInitTime, NULL /* Capabilities */);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a: GetTime(): %r\n", __FUNCTION__, Status));
+ return Status;
+ }
+
+ //
+ // Fetch all blobs.
+ //
+ for (BlobType = 0; BlobType < KernelBlobTypeMax; ++BlobType) {
+ CurrentBlob = &mKernelBlob[BlobType];
+ Status = FetchBlob (CurrentBlob);
+ if (EFI_ERROR (Status)) {
+ goto FreeBlobs;
+ }
+ mTotalBlobBytes += CurrentBlob->Size;
+ }
+ KernelBlob = &mKernelBlob[KernelBlobTypeKernel];
+ InitrdBlob = &mKernelBlob[KernelBlobTypeInitrd];
+ CommandLineBlob = &mKernelBlob[KernelBlobTypeCommandLine];
+
+ if (KernelBlob->Data == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto FreeBlobs;
+ }
+
+ //
+ // Create a new handle with a single VenHw() node device path protocol on it,
+ // plus a custom SimpleFileSystem protocol on it.
+ //
+ FileSystemHandle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (&FileSystemHandle,
+ &gEfiDevicePathProtocolGuid, &mFileSystemDevicePath,
+ &gEfiSimpleFileSystemProtocolGuid, &mFileSystem,
+ NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a: InstallMultipleProtocolInterfaces(): %r\n",
+ __FUNCTION__, Status));
+ goto FreeBlobs;
+ }
+
+ //
+ // Create a device path for the kernel image to be loaded from that will call
+ // back into our file system.
+ //
+ KernelDevicePath = FileDevicePath (FileSystemHandle, KernelBlob->Name);
+ if (KernelDevicePath == NULL) {
+ DEBUG ((EFI_D_ERROR, "%a: failed to allocate kernel device path\n",
+ __FUNCTION__));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto UninstallProtocols;
+ }
+
+ //
+ // Load the image. This should call back into our file system.
+ //
+ Status = gBS->LoadImage (
+ FALSE, // BootPolicy: exact match required
+ gImageHandle, // ParentImageHandle
+ KernelDevicePath,
+ NULL, // SourceBuffer
+ 0, // SourceSize
+ &KernelImageHandle
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a: LoadImage(): %r\n", __FUNCTION__, Status));
+ goto FreeKernelDevicePath;
+ }
+
+ //
+ // Construct the kernel command line.
+ //
+ Status = gBS->OpenProtocol (
+ KernelImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **)&KernelLoadedImage,
+ gImageHandle, // AgentHandle
+ NULL, // ControllerHandle
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (CommandLineBlob->Data == NULL) {
+ KernelLoadedImage->LoadOptionsSize = 0;
+ } else {
+ //
+ // Verify NUL-termination of the command line.
+ //
+ if (CommandLineBlob->Data[CommandLineBlob->Size - 1] != '\0') {
+ DEBUG ((EFI_D_ERROR, "%a: kernel command line is not NUL-terminated\n",
+ __FUNCTION__));
+ Status = EFI_PROTOCOL_ERROR;
+ goto UnloadKernelImage;
+ }
+
+ //
+ // Drop the terminating NUL, convert to UTF-16.
+ //
+ KernelLoadedImage->LoadOptionsSize = (CommandLineBlob->Size - 1) * 2;
+ }
+
+ if (InitrdBlob->Data != NULL) {
+ //
+ // Append ' initrd=<name>' in UTF-16.
+ //
+ KernelLoadedImage->LoadOptionsSize +=
+ (8 + StrLen(InitrdBlob->Name)) * 2;
+ }
+
+ if (KernelLoadedImage->LoadOptionsSize == 0) {
+ KernelLoadedImage->LoadOptions = NULL;
+ } else {
+ //
+ // NUL-terminate in UTF-16.
+ //
+ KernelLoadedImage->LoadOptionsSize += 2;
+
+ KernelLoadedImage->LoadOptions = AllocatePool (
+ KernelLoadedImage->LoadOptionsSize);
+ if (KernelLoadedImage->LoadOptions == NULL) {
+ KernelLoadedImage->LoadOptionsSize = 0;
+ Status = EFI_OUT_OF_RESOURCES;
+ goto UnloadKernelImage;
+ }
+
+ UnicodeSPrintAsciiFormat (
+ KernelLoadedImage->LoadOptions,
+ KernelLoadedImage->LoadOptionsSize,
+ "%a%a%s",
+ (CommandLineBlob->Data == NULL) ? "" : (CHAR8 *)CommandLineBlob->Data,
+ (InitrdBlob->Data == NULL) ? "" : " initrd=",
+ (InitrdBlob->Data == NULL) ? L"" : InitrdBlob->Name
+ );
+ DEBUG ((EFI_D_INFO, "%a: command line: \"%s\"\n", __FUNCTION__,
+ (CHAR16 *)KernelLoadedImage->LoadOptions));
+ }
+
+ //
+ // Start the image.
+ //
+ Status = gBS->StartImage (
+ KernelImageHandle,
+ NULL, // ExitDataSize
+ NULL // ExitData
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a: StartImage(): %r\n", __FUNCTION__, Status));
+ }
+
+ if (KernelLoadedImage->LoadOptions != NULL) {
+ FreePool (KernelLoadedImage->LoadOptions);
+ }
+ KernelLoadedImage->LoadOptionsSize = 0;
+
+UnloadKernelImage:
+ gBS->UnloadImage (KernelImageHandle);
+
+FreeKernelDevicePath:
+ FreePool (KernelDevicePath);
+
+UninstallProtocols:
+ gBS->UninstallMultipleProtocolInterfaces (FileSystemHandle,
+ &gEfiSimpleFileSystemProtocolGuid, &mFileSystem,
+ &gEfiDevicePathProtocolGuid, &mFileSystemDevicePath,
+ NULL);
+
+FreeBlobs:
+ while (BlobType > 0) {
+ CurrentBlob = &mKernelBlob[--BlobType];
+ if (CurrentBlob->Data != NULL) {
+ FreePool (CurrentBlob->Data);
+ CurrentBlob->Size = 0;
+ CurrentBlob->Data = NULL;
+ }
+ }
+
+ return Status;
+}
diff --git a/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c b/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c
new file mode 100644
index 0000000000..bdf2b57fcb
--- /dev/null
+++ b/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c
@@ -0,0 +1,102 @@
+/** @file
+*
+* Copyright (c) 2011-2014, ARM Limited. All rights reserved.
+* Copyright (c) 2014, Linaro Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <PiPei.h>
+
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <libfdt.h>
+
+#include <Guid/EarlyPL011BaseAddress.h>
+#include <Guid/FdtHob.h>
+
+EFI_STATUS
+EFIAPI
+PlatformPeim (
+ VOID
+ )
+{
+ VOID *Base;
+ VOID *NewBase;
+ UINTN FdtSize;
+ UINTN FdtPages;
+ UINT64 *FdtHobData;
+ UINT64 *UartHobData;
+ INT32 Node, Prev;
+ CONST CHAR8 *Compatible;
+ CONST CHAR8 *CompItem;
+ INT32 Len;
+ CONST UINT64 *RegProp;
+ UINT64 UartBase;
+
+
+ Base = (VOID*)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
+ ASSERT (Base != NULL);
+ ASSERT (fdt_check_header (Base) == 0);
+
+ FdtSize = fdt_totalsize (Base) + PcdGet32 (PcdDeviceTreeAllocationPadding);
+ FdtPages = EFI_SIZE_TO_PAGES (FdtSize);
+ NewBase = AllocatePages (FdtPages);
+ ASSERT (NewBase != NULL);
+ fdt_open_into (Base, NewBase, EFI_PAGES_TO_SIZE (FdtPages));
+
+ FdtHobData = BuildGuidHob (&gFdtHobGuid, sizeof *FdtHobData);
+ ASSERT (FdtHobData != NULL);
+ *FdtHobData = (UINTN)NewBase;
+
+ UartHobData = BuildGuidHob (&gEarlyPL011BaseAddressGuid, sizeof *UartHobData);
+ ASSERT (UartHobData != NULL);
+ *UartHobData = 0;
+
+ //
+ // Look for a UART node
+ //
+ for (Prev = 0;; Prev = Node) {
+ Node = fdt_next_node (Base, Prev, NULL);
+ if (Node < 0) {
+ break;
+ }
+
+ //
+ // Check for UART node
+ //
+ Compatible = fdt_getprop (Base, Node, "compatible", &Len);
+
+ //
+ // Iterate over the NULL-separated items in the compatible string
+ //
+ for (CompItem = Compatible; CompItem != NULL && CompItem < Compatible + Len;
+ CompItem += 1 + AsciiStrLen (CompItem)) {
+
+ if (AsciiStrCmp (CompItem, "arm,pl011") == 0) {
+ RegProp = fdt_getprop (Base, Node, "reg", &Len);
+ ASSERT (Len == 16);
+
+ UartBase = fdt64_to_cpu (ReadUnaligned64 (RegProp));
+
+ DEBUG ((EFI_D_INFO, "%a: PL011 UART @ 0x%lx\n", __FUNCTION__, UartBase));
+
+ *UartHobData = UartBase;
+ break;
+ }
+ }
+ }
+
+ BuildFvHob (PcdGet64 (PcdFvBaseAddress), PcdGet32 (PcdFvSize));
+
+ return EFI_SUCCESS;
+}
diff --git a/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.inf b/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.inf
new file mode 100644
index 0000000000..7d456ab3e3
--- /dev/null
+++ b/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.inf
@@ -0,0 +1,52 @@
+#/** @file
+#
+# Copyright (c) 2011-2015, ARM Limited. All rights reserved.
+# Copyright (c) 2014, Linaro Limited. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformPeiLib
+ FILE_GUID = 59C11815-F8DA-4F49-B4FB-EC1E41ED1F06
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformPeiLib
+
+[Sources]
+ PlatformPeiLib.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ ArmVirtPkg/ArmVirtPkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ HobLib
+ FdtLib
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdFvSize
+ gArmVirtTokenSpaceGuid.PcdDeviceTreeAllocationPadding
+
+[Pcd]
+ gArmTokenSpaceGuid.PcdFvBaseAddress
+ gArmVirtTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress
+
+[Guids]
+ gEarlyPL011BaseAddressGuid
+ gFdtHobGuid
+
+[Depex]
+ gEfiPeiMemoryDiscoveredPpiGuid
diff --git a/ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c b/ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
new file mode 100644
index 0000000000..c62eee3be8
--- /dev/null
+++ b/ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
@@ -0,0 +1,358 @@
+/** @file
+
+ Stateful and implicitly initialized fw_cfg library implementation.
+
+ Copyright (C) 2013 - 2014, Red Hat, Inc.
+ Copyright (c) 2011 - 2013, Intel Corporation. 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/BaseMemoryLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/QemuFwCfgLib.h>
+
+STATIC UINTN mFwCfgSelectorAddress;
+STATIC UINTN mFwCfgDataAddress;
+
+
+/**
+ Returns a boolean indicating if the firmware configuration interface is
+ available for library-internal purposes.
+
+ This function never changes fw_cfg state.
+
+ @retval TRUE The interface is available internally.
+ @retval FALSE The interface is not available internally.
+**/
+BOOLEAN
+EFIAPI
+InternalQemuFwCfgIsAvailable (
+ VOID
+ )
+{
+ return (BOOLEAN)(mFwCfgSelectorAddress != 0 && mFwCfgDataAddress != 0);
+}
+
+
+/**
+ Returns a boolean indicating if the firmware configuration interface
+ is available or not.
+
+ This function may change fw_cfg state.
+
+ @retval TRUE The interface is available
+ @retval FALSE The interface is not available
+
+**/
+BOOLEAN
+EFIAPI
+QemuFwCfgIsAvailable (
+ VOID
+ )
+{
+ return InternalQemuFwCfgIsAvailable ();
+}
+
+
+RETURN_STATUS
+EFIAPI
+QemuFwCfgInitialize (
+ VOID
+ )
+{
+ mFwCfgSelectorAddress = (UINTN)PcdGet64 (PcdFwCfgSelectorAddress);
+ mFwCfgDataAddress = (UINTN)PcdGet64 (PcdFwCfgDataAddress);
+
+ if (InternalQemuFwCfgIsAvailable ()) {
+ UINT32 Signature;
+
+ QemuFwCfgSelectItem (QemuFwCfgItemSignature);
+ Signature = QemuFwCfgRead32 ();
+ if (Signature != SIGNATURE_32 ('Q', 'E', 'M', 'U')) {
+ mFwCfgSelectorAddress = 0;
+ mFwCfgDataAddress = 0;
+ }
+ }
+ return RETURN_SUCCESS;
+}
+
+
+/**
+ Selects a firmware configuration item for reading.
+
+ Following this call, any data read from this item will start from the
+ beginning of the configuration item's data.
+
+ @param[in] QemuFwCfgItem Firmware Configuration item to read
+
+**/
+VOID
+EFIAPI
+QemuFwCfgSelectItem (
+ IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem
+ )
+{
+ if (InternalQemuFwCfgIsAvailable ()) {
+ MmioWrite16 (mFwCfgSelectorAddress, SwapBytes16 ((UINT16)QemuFwCfgItem));
+ }
+}
+
+
+/**
+ Reads firmware configuration bytes into a buffer
+
+ @param[in] Size Size in bytes to read
+ @param[in] Buffer Buffer to store data into (OPTIONAL if Size is 0)
+
+**/
+STATIC
+VOID
+EFIAPI
+InternalQemuFwCfgReadBytes (
+ IN UINTN Size,
+ IN VOID *Buffer OPTIONAL
+ )
+{
+ UINTN Left;
+ UINT8 *Ptr;
+ UINT8 *End;
+
+#ifdef MDE_CPU_AARCH64
+ Left = Size & 7;
+#else
+ Left = Size & 3;
+#endif
+
+ Size -= Left;
+ Ptr = Buffer;
+ End = Ptr + Size;
+
+#ifdef MDE_CPU_AARCH64
+ while (Ptr < End) {
+ *(UINT64 *)Ptr = MmioRead64 (mFwCfgDataAddress);
+ Ptr += 8;
+ }
+ if (Left & 4) {
+ *(UINT32 *)Ptr = MmioRead32 (mFwCfgDataAddress);
+ Ptr += 4;
+ }
+#else
+ while (Ptr < End) {
+ *(UINT32 *)Ptr = MmioRead32 (mFwCfgDataAddress);
+ Ptr += 4;
+ }
+#endif
+
+ if (Left & 2) {
+ *(UINT16 *)Ptr = MmioRead16 (mFwCfgDataAddress);
+ Ptr += 2;
+ }
+ if (Left & 1) {
+ *Ptr = MmioRead8 (mFwCfgDataAddress);
+ }
+}
+
+
+/**
+ Reads firmware configuration bytes into a buffer
+
+ If called multiple times, then the data read will continue at the offset of
+ the firmware configuration item where the previous read ended.
+
+ @param[in] Size Size in bytes to read
+ @param[in] Buffer Buffer to store data into
+
+**/
+VOID
+EFIAPI
+QemuFwCfgReadBytes (
+ IN UINTN Size,
+ IN VOID *Buffer
+ )
+{
+ if (InternalQemuFwCfgIsAvailable ()) {
+ InternalQemuFwCfgReadBytes (Size, Buffer);
+ } else {
+ ZeroMem (Buffer, Size);
+ }
+}
+
+/**
+ Write firmware configuration bytes from a buffer
+
+ If called multiple times, then the data written will continue at the offset
+ of the firmware configuration item where the previous write ended.
+
+ @param[in] Size Size in bytes to write
+ @param[in] Buffer Buffer to read data from
+
+**/
+VOID
+EFIAPI
+QemuFwCfgWriteBytes (
+ IN UINTN Size,
+ IN VOID *Buffer
+ )
+{
+ if (InternalQemuFwCfgIsAvailable ()) {
+ UINTN Idx;
+
+ for (Idx = 0; Idx < Size; ++Idx) {
+ MmioWrite8 (mFwCfgDataAddress, ((UINT8 *)Buffer)[Idx]);
+ }
+ }
+}
+
+
+/**
+ Reads a UINT8 firmware configuration value
+
+ @return Value of Firmware Configuration item read
+
+**/
+UINT8
+EFIAPI
+QemuFwCfgRead8 (
+ VOID
+ )
+{
+ UINT8 Result;
+
+ QemuFwCfgReadBytes (sizeof Result, &Result);
+ return Result;
+}
+
+
+/**
+ Reads a UINT16 firmware configuration value
+
+ @return Value of Firmware Configuration item read
+
+**/
+UINT16
+EFIAPI
+QemuFwCfgRead16 (
+ VOID
+ )
+{
+ UINT16 Result;
+
+ QemuFwCfgReadBytes (sizeof Result, &Result);
+ return Result;
+}
+
+
+/**
+ Reads a UINT32 firmware configuration value
+
+ @return Value of Firmware Configuration item read
+
+**/
+UINT32
+EFIAPI
+QemuFwCfgRead32 (
+ VOID
+ )
+{
+ UINT32 Result;
+
+ QemuFwCfgReadBytes (sizeof Result, &Result);
+ return Result;
+}
+
+
+/**
+ Reads a UINT64 firmware configuration value
+
+ @return Value of Firmware Configuration item read
+
+**/
+UINT64
+EFIAPI
+QemuFwCfgRead64 (
+ VOID
+ )
+{
+ UINT64 Result;
+
+ QemuFwCfgReadBytes (sizeof Result, &Result);
+ return Result;
+}
+
+
+/**
+ Find the configuration item corresponding to the firmware configuration file.
+
+ @param[in] Name Name of file to look up.
+ @param[out] Item Configuration item corresponding to the file, to be passed
+ to QemuFwCfgSelectItem ().
+ @param[out] Size Number of bytes in the file.
+
+ @retval RETURN_SUCCESS If file is found.
+ @retval RETURN_NOT_FOUND If file is not found.
+ @retval RETURN_UNSUPPORTED If firmware configuration is unavailable.
+
+**/
+RETURN_STATUS
+EFIAPI
+QemuFwCfgFindFile (
+ IN CONST CHAR8 *Name,
+ OUT FIRMWARE_CONFIG_ITEM *Item,
+ OUT UINTN *Size
+ )
+{
+ UINT32 Count;
+ UINT32 Idx;
+
+ if (!InternalQemuFwCfgIsAvailable ()) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ QemuFwCfgSelectItem (QemuFwCfgItemFileDir);
+ Count = SwapBytes32 (QemuFwCfgRead32 ());
+
+ for (Idx = 0; Idx < Count; ++Idx) {
+ UINT32 FileSize;
+ UINT16 FileSelect;
+ CHAR8 FName[QEMU_FW_CFG_FNAME_SIZE];
+
+ FileSize = QemuFwCfgRead32 ();
+ FileSelect = QemuFwCfgRead16 ();
+ QemuFwCfgRead16 (); // skip the field called "reserved"
+ InternalQemuFwCfgReadBytes (sizeof (FName), FName);
+
+ if (AsciiStrCmp (Name, FName) == 0) {
+ *Item = (FIRMWARE_CONFIG_ITEM) SwapBytes16 (FileSelect);
+ *Size = SwapBytes32 (FileSize);
+ return RETURN_SUCCESS;
+ }
+ }
+
+ return RETURN_NOT_FOUND;
+}
+
+
+/**
+ Determine if S3 support is explicitly enabled.
+
+ @retval TRUE if S3 support is explicitly enabled.
+ FALSE otherwise. This includes unavailability of the firmware
+ configuration interface.
+**/
+BOOLEAN
+EFIAPI
+QemuFwCfgS3Enabled (
+ VOID
+ )
+{
+ return FALSE;
+}
diff --git a/ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf b/ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
new file mode 100644
index 0000000000..42f21f20c0
--- /dev/null
+++ b/ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
@@ -0,0 +1,52 @@
+## @file
+#
+# Stateful, implicitly initialized fw_cfg library.
+#
+# Copyright (C) 2013 - 2014, Red Hat, Inc.
+# Copyright (c) 2008 - 2012, Intel Corporation. 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 = QemuFwCfgLib
+ FILE_GUID = B271F41F-B841-48A9-BA8D-545B4BC2E2BF
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = QemuFwCfgLib|DXE_DRIVER
+
+ CONSTRUCTOR = QemuFwCfgInitialize
+
+#
+# The following information is for reference only and not required by the build
+# tools.
+#
+# VALID_ARCHITECTURES = ARM AARCH64
+#
+
+[Sources]
+ QemuFwCfgLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+ ArmVirtPkg/ArmVirtPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ IoLib
+ PcdLib
+
+[Pcd]
+ gArmVirtTokenSpaceGuid.PcdFwCfgSelectorAddress
+ gArmVirtTokenSpaceGuid.PcdFwCfgDataAddress
diff --git a/ArmVirtPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.c b/ArmVirtPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.c
new file mode 100644
index 0000000000..70204ac22a
--- /dev/null
+++ b/ArmVirtPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.c
@@ -0,0 +1,196 @@
+/** @file
+ Implement EFI RealTimeClock runtime services via Xen shared info page
+
+ Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+#include <PiDxe.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+
+/**
+ Converts Epoch seconds (elapsed since 1970 JANUARY 01, 00:00:00 UTC) to EFI_TIME
+ **/
+STATIC
+VOID
+EpochToEfiTime (
+ IN UINTN EpochSeconds,
+ OUT EFI_TIME *Time
+ )
+{
+ UINTN a;
+ UINTN b;
+ UINTN c;
+ UINTN d;
+ UINTN g;
+ UINTN j;
+ UINTN m;
+ UINTN y;
+ UINTN da;
+ UINTN db;
+ UINTN dc;
+ UINTN dg;
+ UINTN hh;
+ UINTN mm;
+ UINTN ss;
+ UINTN J;
+
+ J = (EpochSeconds / 86400) + 2440588;
+ j = J + 32044;
+ g = j / 146097;
+ dg = j % 146097;
+ c = (((dg / 36524) + 1) * 3) / 4;
+ dc = dg - (c * 36524);
+ b = dc / 1461;
+ db = dc % 1461;
+ a = (((db / 365) + 1) * 3) / 4;
+ da = db - (a * 365);
+ y = (g * 400) + (c * 100) + (b * 4) + a;
+ m = (((da * 5) + 308) / 153) - 2;
+ d = da - (((m + 4) * 153) / 5) + 122;
+
+ Time->Year = y - 4800 + ((m + 2) / 12);
+ Time->Month = ((m + 2) % 12) + 1;
+ Time->Day = d + 1;
+
+ ss = EpochSeconds % 60;
+ a = (EpochSeconds - ss) / 60;
+ mm = a % 60;
+ b = (a - mm) / 60;
+ hh = b % 24;
+
+ Time->Hour = hh;
+ Time->Minute = mm;
+ Time->Second = ss;
+ Time->Nanosecond = 0;
+
+}
+
+/**
+ Returns the current time and date information, and the time-keeping capabilities
+ of the hardware platform.
+
+ @param Time A pointer to storage to receive a snapshot of the current time.
+ @param Capabilities An optional pointer to a buffer to receive the real time clock
+ device's capabilities.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER Time is NULL.
+ @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+LibGetTime (
+ OUT EFI_TIME *Time,
+ OUT EFI_TIME_CAPABILITIES *Capabilities
+ )
+{
+ ASSERT (Time != NULL);
+
+ //
+ // For now, there is nothing that we can do besides returning a bogus time,
+ // as Xen's timekeeping uses a shared info page which cannot be shared
+ // between UEFI and the OS
+ //
+ EpochToEfiTime(1421770011, Time);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Sets the current local time and date information.
+
+ @param Time A pointer to the current time.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER A time field is out of range.
+ @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+LibSetTime (
+ IN EFI_TIME *Time
+ )
+{
+ return EFI_DEVICE_ERROR;
+}
+
+
+/**
+ Returns the current wakeup alarm clock setting.
+
+ @param Enabled Indicates if the alarm is currently enabled or disabled.
+ @param Pending Indicates if the alarm signal is pending and requires acknowledgement.
+ @param Time The current alarm setting.
+
+ @retval EFI_SUCCESS The alarm settings were returned.
+ @retval EFI_INVALID_PARAMETER Any parameter is NULL.
+ @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error.
+ @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.
+
+**/
+EFI_STATUS
+EFIAPI
+LibGetWakeupTime (
+ OUT BOOLEAN *Enabled,
+ OUT BOOLEAN *Pending,
+ OUT EFI_TIME *Time
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Sets the system wakeup alarm clock time.
+
+ @param Enabled Enable or disable the wakeup alarm.
+ @param Time If Enable is TRUE, the time to set the wakeup alarm for.
+
+ @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled. If
+ Enable is FALSE, then the wakeup alarm was disabled.
+ @retval EFI_INVALID_PARAMETER A time field is out of range.
+ @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error.
+ @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.
+
+**/
+EFI_STATUS
+EFIAPI
+LibSetWakeupTime (
+ IN BOOLEAN Enabled,
+ OUT EFI_TIME *Time
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ This is the declaration of an EFI image entry point. This can be the entry point to an application
+ written to this specification, an EFI boot service driver, or an EFI runtime driver.
+
+ @param ImageHandle Handle that identifies the loaded image.
+ @param SystemTable System Table for this image.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+LibRtcInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return EFI_SUCCESS;
+}
diff --git a/ArmVirtPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.inf b/ArmVirtPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.inf
new file mode 100644
index 0000000000..aafbfda6b4
--- /dev/null
+++ b/ArmVirtPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.inf
@@ -0,0 +1,38 @@
+#/** @file
+#
+# Copyright (c) 2015, L 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 = XenRealTimeClockLib
+ FILE_GUID = EC2557E8-7005-430B-9F6F-9BA109698248
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RealTimeClockLib|DXE_CORE DXE_DRIVER UEFI_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION
+
+[Sources.common]
+ XenRealTimeClockLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+ UefiLib
+ DebugLib
+ DxeServicesTableLib
+ UefiRuntimeLib
+
+[Guids]
+ gEfiEventVirtualAddressChangeGuid