diff --git a/ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManager.c b/ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManager.c
new file mode 100644
index 0000000000..e8c1b13c8f
--- /dev/null
+++ b/ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManager.c
@@ -0,0 +1,1065 @@
+/** @file
+ Configuration Manager Dxe
+
+ Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - Cm or CM - Configuration Manager
+ - Obj or OBJ - Object
+**/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "ConfigurationManager.h"
+
+//
+// The platform configuration repository information.
+//
+STATIC
+EDKII_PLATFORM_REPOSITORY_INFO mKvmtoolPlatRepositoryInfo = {
+ //
+ // Configuration Manager information
+ //
+ { CONFIGURATION_MANAGER_REVISION, CFG_MGR_OEM_ID },
+
+ //
+ // ACPI Table List
+ //
+ {
+ //
+ // FADT Table
+ //
+ {
+ EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
+ EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE_REVISION,
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt),
+ NULL
+ },
+ //
+ // GTDT Table
+ //
+ {
+ EFI_ACPI_6_3_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE,
+ EFI_ACPI_6_3_GENERIC_TIMER_DESCRIPTION_TABLE_REVISION,
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdGtdt),
+ NULL
+ },
+ //
+ // MADT Table
+ //
+ {
+ EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE,
+ EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION,
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdMadt),
+ NULL
+ },
+ //
+ // SPCR Table
+ //
+ {
+ EFI_ACPI_6_3_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
+ EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION,
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSpcr),
+ NULL
+ },
+ //
+ // DSDT Table
+ //
+ {
+ EFI_ACPI_6_3_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
+ 0, // Unused
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdDsdt),
+ (EFI_ACPI_DESCRIPTION_HEADER *)dsdt_aml_code
+ },
+ //
+ // SSDT Cpu Hierarchy Table
+ //
+ {
+ EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
+ 0, // Unused
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtCpuTopology),
+ NULL
+ },
+ //
+ // DBG2 Table
+ //
+ {
+ EFI_ACPI_6_3_DEBUG_PORT_2_TABLE_SIGNATURE,
+ EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION,
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdDbg2),
+ NULL
+ },
+ //
+ // PCI MCFG Table
+ //
+ {
+ EFI_ACPI_6_3_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
+ EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION,
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdMcfg),
+ NULL
+ },
+ //
+ // SSDT table describing the PCI root complex
+ //
+ {
+ EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
+ 0, // Unused
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtPciExpress),
+ NULL
+ },
+ //
+ // IORT Table
+ //
+ {
+ EFI_ACPI_6_3_IO_REMAPPING_TABLE_SIGNATURE,
+ EFI_ACPI_IO_REMAPPING_TABLE_REVISION,
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdIort),
+ NULL
+ },
+ },
+
+ //
+ // Power management profile information
+ //
+ { EFI_ACPI_6_3_PM_PROFILE_ENTERPRISE_SERVER }, // PowerManagement Profile
+
+ //
+ // ITS group node
+ //
+ {
+ //
+ // Reference token for this Iort node
+ //
+ REFERENCE_TOKEN (ItsGroupInfo),
+ //
+ // The number of ITS identifiers in the ITS node.
+ //
+ 1,
+ //
+ // Reference token for the ITS identifier array
+ //
+ REFERENCE_TOKEN (ItsIdentifierArray)
+ },
+
+ //
+ // ITS identifier array
+ //
+ {
+ { 0 }, // The ITS Identifier
+ },
+
+ //
+ // Root Complex node info
+ //
+ {
+ //
+ // Reference token for this Iort node
+ //
+ REFERENCE_TOKEN (RootComplexInfo),
+ //
+ // Number of ID mappings
+ //
+ 1,
+ //
+ // Reference token for the ID mapping array
+ //
+ REFERENCE_TOKEN (DeviceIdMapping[0]),
+ //
+ // Memory access properties : Cache coherent attributes
+ //
+ EFI_ACPI_IORT_MEM_ACCESS_PROP_CCA,
+ //
+ // Memory access properties : Allocation hints
+ //
+ 0,
+ //
+ // Memory access properties : Memory access flags
+ //
+ 0,
+ //
+ // ATS attributes
+ //
+ EFI_ACPI_IORT_ROOT_COMPLEX_ATS_UNSUPPORTED,
+ //
+ // PCI segment number
+ //
+ 0,
+ ///
+ /// Memory address size limit
+ ///
+ MEMORY_ADDRESS_SIZE_LIMIT
+ },
+
+ //
+ // Array of Device ID mappings
+ //
+ {
+ //
+ // Device ID mapping for Root complex node
+ // RootComplex -> ITS Group
+ //
+ {
+ //
+ // Input base
+ //
+ 0x0,
+ //
+ // Number of input IDs
+ //
+ 0x0000FFFF,
+ //
+ // Output Base
+ //
+ 0x0,
+ //
+ // Output reference
+ //
+ REFERENCE_TOKEN (ItsGroupInfo),
+ //
+ // Flags
+ //
+ 0
+ },
+ },
+};
+
+/**
+ A helper function for returning the Configuration Manager Objects.
+
+ @param [in] CmObjectId The Configuration Manager Object ID.
+ @param [in] Object Pointer to the Object(s).
+ @param [in] ObjectSize Total size of the Object(s).
+ @param [in] ObjectCount Number of Objects.
+ @param [in, out] CmObjectDesc Pointer to the Configuration Manager Object
+ descriptor describing the requested Object.
+
+ @retval EFI_SUCCESS Success.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+HandleCmObject (
+ IN CONST CM_OBJECT_ID CmObjectId,
+ IN VOID *Object,
+ IN CONST UINTN ObjectSize,
+ IN CONST UINTN ObjectCount,
+ IN OUT CM_OBJ_DESCRIPTOR *CONST CmObjectDesc
+ )
+{
+ CmObjectDesc->ObjectId = CmObjectId;
+ CmObjectDesc->Size = ObjectSize;
+ CmObjectDesc->Data = Object;
+ CmObjectDesc->Count = ObjectCount;
+ DEBUG ((
+ DEBUG_INFO,
+ "INFO: CmObjectId = " FMT_CM_OBJECT_ID ", "
+ "Ptr = 0x%p, Size = %lu, Count = %lu\n",
+ CmObjectId,
+ CmObjectDesc->Data,
+ CmObjectDesc->Size,
+ CmObjectDesc->Count
+ ));
+ return EFI_SUCCESS;
+}
+
+/**
+ A helper function for returning the Configuration Manager Objects that
+ match the token.
+
+ @param [in] This Pointer to the Configuration Manager Protocol.
+ @param [in] CmObjectId The Configuration Manager Object ID.
+ @param [in] Object Pointer to the Object(s).
+ @param [in] ObjectSize Total size of the Object(s).
+ @param [in] ObjectCount Number of Objects.
+ @param [in] Token A token identifying the object.
+ @param [in] HandlerProc A handler function to search the object
+ referenced by the token.
+ @param [in, out] CmObjectDesc Pointer to the Configuration Manager Object
+ descriptor describing the requested Object.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_NOT_FOUND The required object information is not found.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+HandleCmObjectRefByToken (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST This,
+ IN CONST CM_OBJECT_ID CmObjectId,
+ IN VOID *Object,
+ IN CONST UINTN ObjectSize,
+ IN CONST UINTN ObjectCount,
+ IN CONST CM_OBJECT_TOKEN Token,
+ IN CONST CM_OBJECT_HANDLER_PROC HandlerProc,
+ IN OUT CM_OBJ_DESCRIPTOR *CONST CmObjectDesc
+ )
+{
+ EFI_STATUS Status;
+
+ CmObjectDesc->ObjectId = CmObjectId;
+ if (Token == CM_NULL_TOKEN) {
+ CmObjectDesc->Size = ObjectSize;
+ CmObjectDesc->Data = Object;
+ CmObjectDesc->Count = ObjectCount;
+ Status = EFI_SUCCESS;
+ } else {
+ Status = HandlerProc (This, CmObjectId, Token, CmObjectDesc);
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "INFO: Token = 0x%p, CmObjectId = " FMT_CM_OBJECT_ID ", "
+ "Ptr = 0x%p, Size = %lu, Count = %lu\n",
+ (VOID *)Token,
+ CmObjectId,
+ CmObjectDesc->Data,
+ CmObjectDesc->Size,
+ CmObjectDesc->Count
+ ));
+ return Status;
+}
+
+/**
+ Return an ITS identifier array.
+
+ @param [in] This Pointer to the Configuration Manager Protocol.
+ @param [in] CmObjectId The Configuration Manager Object ID.
+ @param [in] Token A token for identifying the object
+ @param [out] CmObject Pointer to the Configuration Manager Object
+ descriptor describing the requested Object.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_NOT_FOUND The required object information is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetItsIdentifierArray (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST This,
+ IN CONST CM_OBJECT_ID CmObjectId,
+ IN CONST CM_OBJECT_TOKEN Token,
+ OUT CM_OBJ_DESCRIPTOR *CONST CmObject
+ )
+{
+ EDKII_PLATFORM_REPOSITORY_INFO *PlatformRepo;
+
+ if ((This == NULL) || (CmObject == NULL)) {
+ ASSERT (This != NULL);
+ ASSERT (CmObject != NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PlatformRepo = This->PlatRepoInfo;
+
+ if (Token != (CM_OBJECT_TOKEN)&PlatformRepo->ItsIdentifierArray) {
+ return EFI_NOT_FOUND;
+ }
+
+ CmObject->ObjectId = CmObjectId;
+ CmObject->Size = sizeof (PlatformRepo->ItsIdentifierArray);
+ CmObject->Data = (VOID *)&PlatformRepo->ItsIdentifierArray;
+ CmObject->Count = ARRAY_SIZE (PlatformRepo->ItsIdentifierArray);
+ return EFI_SUCCESS;
+}
+
+/**
+ Return a device Id mapping array.
+
+ @param [in] This Pointer to the Configuration Manager Protocol.
+ @param [in] CmObjectId The Configuration Manager Object ID.
+ @param [in] Token A token for identifying the object
+ @param [out] CmObject Pointer to the Configuration Manager Object
+ descriptor describing the requested Object.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_NOT_FOUND The required object information is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetDeviceIdMappingArray (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST This,
+ IN CONST CM_OBJECT_ID CmObjectId,
+ IN CONST CM_OBJECT_TOKEN Token,
+ OUT CM_OBJ_DESCRIPTOR *CONST CmObject
+ )
+{
+ EDKII_PLATFORM_REPOSITORY_INFO *PlatformRepo;
+
+ if ((This == NULL) || (CmObject == NULL)) {
+ ASSERT (This != NULL);
+ ASSERT (CmObject != NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PlatformRepo = This->PlatRepoInfo;
+
+ if (Token != (CM_OBJECT_TOKEN)&PlatformRepo->DeviceIdMapping[0]) {
+ return EFI_NOT_FOUND;
+ }
+
+ CmObject->ObjectId = CmObjectId;
+ CmObject->Size = sizeof (CM_ARM_ID_MAPPING);
+ CmObject->Data = (VOID *)Token;
+ CmObject->Count = 1;
+ return EFI_SUCCESS;
+}
+
+/**
+ Function pointer called by the parser to add information.
+
+ Callback function that the parser can use to add new
+ CmObj. This function must copy the CmObj data and not rely on
+ the parser preserving the CmObj memory.
+ This function is responsible of the Token allocation.
+
+ @param [in] ParserHandle A handle to the parser instance.
+ @param [in] Context A pointer to the caller's context provided in
+ HwInfoParserInit ().
+ @param [in] CmObjDesc CM_OBJ_DESCRIPTOR containing the CmObj(s) to add.
+ @param [out] Token If provided and success, contain the token
+ generated for the CmObj.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+HwInfoAdd (
+ IN HW_INFO_PARSER_HANDLE ParserHandle,
+ IN VOID *Context,
+ IN CONST CM_OBJ_DESCRIPTOR *CmObjDesc,
+ OUT CM_OBJECT_TOKEN *Token OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EDKII_PLATFORM_REPOSITORY_INFO *PlatformRepo;
+
+ if ((ParserHandle == NULL) ||
+ (Context == NULL) ||
+ (CmObjDesc == NULL))
+ {
+ ASSERT (ParserHandle != NULL);
+ ASSERT (Context != NULL);
+ ASSERT (CmObjDesc != NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PlatformRepo = (EDKII_PLATFORM_REPOSITORY_INFO *)Context;
+
+ DEBUG_CODE_BEGIN ();
+ //
+ // Print the received objects.
+ //
+ ParseCmObjDesc (CmObjDesc);
+ DEBUG_CODE_END ();
+
+ Status = DynPlatRepoAddObject (
+ PlatformRepo->DynamicPlatformRepo,
+ CmObjDesc,
+ Token
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return Status;
+}
+
+/**
+ Cleanup the platform configuration repository.
+
+ @param [in] This Pointer to the Configuration Manager Protocol.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+CleanupPlatformRepository (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST This
+ )
+{
+ EFI_STATUS Status;
+ EDKII_PLATFORM_REPOSITORY_INFO *PlatformRepo;
+
+ if (This == NULL) {
+ ASSERT (This != NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PlatformRepo = This->PlatRepoInfo;
+
+ //
+ // Shutdown the dynamic repo and free all objects.
+ //
+ Status = DynamicPlatRepoShutdown (PlatformRepo->DynamicPlatformRepo);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ //
+ // Shutdown parser.
+ //
+ Status = HwInfoParserShutdown (PlatformRepo->FdtParserHandle);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return Status;
+}
+
+/**
+ Initialize the platform configuration repository.
+
+ @param [in] This Pointer to the Configuration Manager Protocol.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_OUT_OF_RESOURCES An allocation has failed.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+InitializePlatformRepository (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST This
+ )
+{
+ EFI_STATUS Status;
+ EDKII_PLATFORM_REPOSITORY_INFO *PlatformRepo;
+ VOID *Hob;
+
+ if (This == NULL) {
+ ASSERT (This != NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Hob = GetFirstGuidHob (&gFdtHobGuid);
+ if ((Hob == NULL) || (GET_GUID_HOB_DATA_SIZE (Hob) != sizeof (UINT64))) {
+ ASSERT (FALSE);
+ ASSERT (GET_GUID_HOB_DATA_SIZE (Hob) != sizeof (UINT64));
+ return EFI_NOT_FOUND;
+ }
+
+ PlatformRepo = This->PlatRepoInfo;
+ PlatformRepo->FdtBase = (VOID *)*(UINTN *)GET_GUID_HOB_DATA (Hob);
+
+ //
+ // Initialise the dynamic platform repository.
+ //
+ Status = DynamicPlatRepoInit (&PlatformRepo->DynamicPlatformRepo);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ //
+ // Initialise the FDT parser
+ //
+ Status = HwInfoParserInit (
+ PlatformRepo->FdtBase,
+ PlatformRepo,
+ HwInfoAdd,
+ &PlatformRepo->FdtParserHandle
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ goto ErrorHandler;
+ }
+
+ Status = HwInfoParse (PlatformRepo->FdtParserHandle);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ goto ErrorHandler;
+ }
+
+ Status = DynamicPlatRepoFinalise (PlatformRepo->DynamicPlatformRepo);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ goto ErrorHandler;
+ }
+
+ return EFI_SUCCESS;
+
+ErrorHandler:
+ CleanupPlatformRepository (This);
+ return Status;
+}
+
+/**
+ Return a standard namespace object.
+
+ @param [in] This Pointer to the Configuration Manager Protocol.
+ @param [in] CmObjectId The Configuration Manager Object ID.
+ @param [in] Token An optional token identifying the object. If
+ unused this must be CM_NULL_TOKEN.
+ @param [in, out] CmObject Pointer to the Configuration Manager Object
+ descriptor describing the requested Object.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_NOT_FOUND The required object information is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetStandardNameSpaceObject (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST This,
+ IN CONST CM_OBJECT_ID CmObjectId,
+ IN CONST CM_OBJECT_TOKEN Token OPTIONAL,
+ IN OUT CM_OBJ_DESCRIPTOR *CONST CmObject
+ )
+{
+ EFI_STATUS Status;
+ EDKII_PLATFORM_REPOSITORY_INFO *PlatformRepo;
+ UINTN AcpiTableCount;
+ CM_OBJ_DESCRIPTOR CmObjDesc;
+
+ if ((This == NULL) || (CmObject == NULL)) {
+ ASSERT (This != NULL);
+ ASSERT (CmObject != NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_NOT_FOUND;
+ PlatformRepo = This->PlatRepoInfo;
+
+ switch (GET_CM_OBJECT_ID (CmObjectId)) {
+ case EStdObjCfgMgrInfo:
+ Status = HandleCmObject (
+ CmObjectId,
+ &PlatformRepo->CmInfo,
+ sizeof (PlatformRepo->CmInfo),
+ 1,
+ CmObject
+ );
+ break;
+
+ case EStdObjAcpiTableList:
+ AcpiTableCount = ARRAY_SIZE (PlatformRepo->CmAcpiTableList);
+
+ //
+ // Get Pci config space information.
+ //
+ Status = DynamicPlatRepoGetObject (
+ PlatformRepo->DynamicPlatformRepo,
+ CREATE_CM_ARM_OBJECT_ID (EArmObjPciConfigSpaceInfo),
+ CM_NULL_TOKEN,
+ &CmObjDesc
+ );
+ if (Status == EFI_NOT_FOUND) {
+ //
+ // The last 3 tables are for PCIe. If PCIe information is not
+ // present, Kvmtool was launched without the PCIe option.
+ // Therefore, reduce the table count by 3.
+ //
+ AcpiTableCount -= 3;
+ } else if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ //
+ // Get the Gic version.
+ //
+ Status = DynamicPlatRepoGetObject (
+ PlatformRepo->DynamicPlatformRepo,
+ CREATE_CM_ARM_OBJECT_ID (EArmObjGicDInfo),
+ CM_NULL_TOKEN,
+ &CmObjDesc
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ if (((CM_ARM_GICD_INFO *)CmObjDesc.Data)->GicVersion < 3) {
+ //
+ // IORT is only required for GicV3/4
+ //
+ AcpiTableCount -= 1;
+ }
+
+ Status = HandleCmObject (
+ CmObjectId,
+ PlatformRepo->CmAcpiTableList,
+ (sizeof (PlatformRepo->CmAcpiTableList[0]) * AcpiTableCount),
+ AcpiTableCount,
+ CmObject
+ );
+ break;
+
+ default:
+ Status = EFI_NOT_FOUND;
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: CmObjectId " FMT_CM_OBJECT_ID ". Status = %r\n",
+ CmObjectId,
+ Status
+ ));
+ break;
+ }
+
+ return Status;
+}
+
+/**
+ Return an ARM namespace object.
+
+ @param [in] This Pointer to the Configuration Manager Protocol.
+ @param [in] CmObjectId The Configuration Manager Object ID.
+ @param [in] Token An optional token identifying the object. If
+ unused this must be CM_NULL_TOKEN.
+ @param [in, out] CmObject Pointer to the Configuration Manager Object
+ descriptor describing the requested Object.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_NOT_FOUND The required object information is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetArmNameSpaceObject (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST This,
+ IN CONST CM_OBJECT_ID CmObjectId,
+ IN CONST CM_OBJECT_TOKEN Token OPTIONAL,
+ IN OUT CM_OBJ_DESCRIPTOR *CONST CmObject
+ )
+{
+ EFI_STATUS Status;
+ EDKII_PLATFORM_REPOSITORY_INFO *PlatformRepo;
+
+ if ((This == NULL) || (CmObject == NULL)) {
+ ASSERT (This != NULL);
+ ASSERT (CmObject != NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_NOT_FOUND;
+ PlatformRepo = This->PlatRepoInfo;
+
+ //
+ // First check among the static objects.
+ //
+ switch (GET_CM_OBJECT_ID (CmObjectId)) {
+ case EArmObjPowerManagementProfileInfo:
+ Status = HandleCmObject (
+ CmObjectId,
+ &PlatformRepo->PmProfileInfo,
+ sizeof (PlatformRepo->PmProfileInfo),
+ 1,
+ CmObject
+ );
+ break;
+
+ case EArmObjItsGroup:
+ Status = HandleCmObject (
+ CmObjectId,
+ &PlatformRepo->ItsGroupInfo,
+ sizeof (PlatformRepo->ItsGroupInfo),
+ 1,
+ CmObject
+ );
+ break;
+
+ case EArmObjGicItsIdentifierArray:
+ Status = HandleCmObjectRefByToken (
+ This,
+ CmObjectId,
+ PlatformRepo->ItsIdentifierArray,
+ sizeof (PlatformRepo->ItsIdentifierArray),
+ ARRAY_SIZE (PlatformRepo->ItsIdentifierArray),
+ Token,
+ GetItsIdentifierArray,
+ CmObject
+ );
+ break;
+
+ case EArmObjRootComplex:
+ Status = HandleCmObject (
+ CmObjectId,
+ &PlatformRepo->RootComplexInfo,
+ sizeof (PlatformRepo->RootComplexInfo),
+ 1,
+ CmObject
+ );
+ break;
+
+ case EArmObjIdMappingArray:
+ Status = HandleCmObjectRefByToken (
+ This,
+ CmObjectId,
+ PlatformRepo->DeviceIdMapping,
+ sizeof (PlatformRepo->DeviceIdMapping),
+ ARRAY_SIZE (PlatformRepo->DeviceIdMapping),
+ Token,
+ GetDeviceIdMappingArray,
+ CmObject
+ );
+ break;
+
+ default:
+ //
+ // No match found among the static objects.
+ // Check the dynamic objects.
+ //
+ Status = DynamicPlatRepoGetObject (
+ PlatformRepo->DynamicPlatformRepo,
+ CmObjectId,
+ Token,
+ CmObject
+ );
+ break;
+ } // switch
+
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((
+ DEBUG_INFO,
+ "INFO: CmObjectId " FMT_CM_OBJECT_ID ". Status = %r\n",
+ CmObjectId,
+ Status
+ ));
+ } else {
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return Status;
+}
+
+/**
+ Return an OEM namespace object.
+
+ @param [in] This Pointer to the Configuration Manager Protocol.
+ @param [in] CmObjectId The Configuration Manager Object ID.
+ @param [in] Token An optional token identifying the object. If
+ unused this must be CM_NULL_TOKEN.
+ @param [in, out] CmObject Pointer to the Configuration Manager Object
+ descriptor describing the requested Object.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_NOT_FOUND The required object information is not found.
+**/
+EFI_STATUS
+EFIAPI
+GetOemNameSpaceObject (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST This,
+ IN CONST CM_OBJECT_ID CmObjectId,
+ IN CONST CM_OBJECT_TOKEN Token OPTIONAL,
+ IN OUT CM_OBJ_DESCRIPTOR *CONST CmObject
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ if ((This == NULL) || (CmObject == NULL)) {
+ ASSERT (This != NULL);
+ ASSERT (CmObject != NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (GET_CM_OBJECT_ID (CmObjectId)) {
+ default:
+ Status = EFI_NOT_FOUND;
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: CmObjectId " FMT_CM_OBJECT_ID ". Status = %r\n",
+ CmObjectId,
+ Status
+ ));
+ break;
+ }
+
+ return Status;
+}
+
+/**
+ The GetObject function defines the interface implemented by the
+ Configuration Manager Protocol for returning the Configuration
+ Manager Objects.
+
+ @param [in] This Pointer to the Configuration Manager Protocol.
+ @param [in] CmObjectId The Configuration Manager Object ID.
+ @param [in] Token An optional token identifying the object. If
+ unused this must be CM_NULL_TOKEN.
+ @param [in, out] CmObject Pointer to the Configuration Manager Object
+ descriptor describing the requested Object.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_NOT_FOUND The required object information is not found.
+**/
+EFI_STATUS
+EFIAPI
+ArmKvmtoolPlatformGetObject (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST This,
+ IN CONST CM_OBJECT_ID CmObjectId,
+ IN CONST CM_OBJECT_TOKEN Token OPTIONAL,
+ IN OUT CM_OBJ_DESCRIPTOR *CONST CmObject
+ )
+{
+ EFI_STATUS Status;
+
+ if ((This == NULL) || (CmObject == NULL)) {
+ ASSERT (This != NULL);
+ ASSERT (CmObject != NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (GET_CM_NAMESPACE_ID (CmObjectId)) {
+ case EObjNameSpaceStandard:
+ Status = GetStandardNameSpaceObject (This, CmObjectId, Token, CmObject);
+ break;
+ case EObjNameSpaceArm:
+ Status = GetArmNameSpaceObject (This, CmObjectId, Token, CmObject);
+ break;
+ case EObjNameSpaceOem:
+ Status = GetOemNameSpaceObject (This, CmObjectId, Token, CmObject);
+ break;
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: Unknown Namespace CmObjectId " FMT_CM_OBJECT_ID ". "
+ "Status = %r\n",
+ CmObjectId,
+ Status
+ ));
+ break;
+ }
+
+ return Status;
+}
+
+/**
+ The SetObject function defines the interface implemented by the
+ Configuration Manager Protocol for updating the Configuration
+ Manager Objects.
+
+ @param [in] This Pointer to the Configuration Manager Protocol.
+ @param [in] CmObjectId The Configuration Manager Object ID.
+ @param [in] Token An optional token identifying the object. If
+ unused this must be CM_NULL_TOKEN.
+ @param [in] CmObject Pointer to the Configuration Manager Object
+ descriptor describing the Object.
+
+ @retval EFI_UNSUPPORTED This operation is not supported.
+**/
+EFI_STATUS
+EFIAPI
+ArmKvmtoolPlatformSetObject (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST This,
+ IN CONST CM_OBJECT_ID CmObjectId,
+ IN CONST CM_OBJECT_TOKEN Token OPTIONAL,
+ IN CM_OBJ_DESCRIPTOR *CONST CmObject
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+//
+// A structure describing the configuration manager protocol interface.
+//
+STATIC
+CONST
+EDKII_CONFIGURATION_MANAGER_PROTOCOL mKvmtoolPlatformConfigManagerProtocol = {
+ CREATE_REVISION (1, 0),
+ ArmKvmtoolPlatformGetObject,
+ ArmKvmtoolPlatformSetObject,
+ &mKvmtoolPlatRepositoryInfo
+};
+
+/**
+ Entrypoint of Configuration Manager Dxe.
+
+ @param ImageHandle
+ @param SystemTable
+
+ @retval EFI_SUCCESS
+ @retval EFI_LOAD_ERROR
+ @retval EFI_OUT_OF_RESOURCES
+**/
+EFI_STATUS
+EFIAPI
+ConfigurationManagerDxeInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->InstallProtocolInterface (
+ &ImageHandle,
+ &gEdkiiConfigurationManagerProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ (VOID *)&mKvmtoolPlatformConfigManagerProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: Failed to get Install Configuration Manager Protocol." \
+ " Status = %r\n",
+ Status
+ ));
+ return Status;
+ }
+
+ Status = InitializePlatformRepository (
+ &mKvmtoolPlatformConfigManagerProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: Failed to initialize the Platform Configuration Repository." \
+ " Status = %r\n",
+ Status
+ ));
+ goto ErrorHandler;
+ }
+
+ return Status;
+
+ErrorHandler:
+ gBS->UninstallProtocolInterface (
+ &ImageHandle,
+ &gEdkiiConfigurationManagerProtocolGuid,
+ (VOID *)&mKvmtoolPlatformConfigManagerProtocol
+ );
+ return Status;
+}
+
+/**
+ Unload function for this image.
+
+ @param ImageHandle Handle for the image of this driver.
+
+ @retval EFI_SUCCESS Driver unloaded successfully.
+ @retval other Driver can not unloaded.
+**/
+EFI_STATUS
+EFIAPI
+ConfigurationManagerDxeUnloadImage (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ return CleanupPlatformRepository (&mKvmtoolPlatformConfigManagerProtocol);
+}
diff --git a/ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManager.h b/ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManager.h
new file mode 100644
index 0000000000..3373948bc4
--- /dev/null
+++ b/ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManager.h
@@ -0,0 +1,125 @@
+/** @file
+
+ Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - Cm or CM - Configuration Manager
+ - Obj or OBJ - Object
+**/
+
+#ifndef CONFIGURATION_MANAGER_H_
+#define CONFIGURATION_MANAGER_H_
+
+///
+/// C array containing the compiled AML template.
+/// This symbol is defined in the auto generated C file
+/// containing the AML bytecode array.
+///
+extern CHAR8 dsdt_aml_code[];
+
+///
+/// The configuration manager version.
+///
+#define CONFIGURATION_MANAGER_REVISION CREATE_REVISION (1, 0)
+
+///
+/// The OEM ID
+///
+#define CFG_MGR_OEM_ID { 'A', 'R', 'M', 'L', 'T', 'D' }
+
+///
+/// Memory address size limit. Assume the whole address space.
+///
+#define MEMORY_ADDRESS_SIZE_LIMIT 64
+
+/** A function that prepares Configuration Manager Objects for returning.
+
+ @param [in] This Pointer to the Configuration Manager Protocol.
+ @param [in] CmObjectId The Configuration Manager Object ID.
+ @param [in] Token A token for identifying the object.
+ @param [out] CmObject Pointer to the Configuration Manager Object
+ descriptor describing the requested Object.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_NOT_FOUND The required object information is not found.
+**/
+typedef EFI_STATUS (*CM_OBJECT_HANDLER_PROC) (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST This,
+ IN CONST CM_OBJECT_ID CmObjectId,
+ IN CONST CM_OBJECT_TOKEN Token,
+ IN OUT CM_OBJ_DESCRIPTOR *CONST CmObject
+ );
+
+///
+/// A helper macro for mapping a reference token.
+///
+#define REFERENCE_TOKEN(Field) \
+ (CM_OBJECT_TOKEN)((UINT8*)&mKvmtoolPlatRepositoryInfo + \
+ OFFSET_OF (EDKII_PLATFORM_REPOSITORY_INFO, Field))
+
+///
+/// The number of ACPI tables to install
+///
+#define PLAT_ACPI_TABLE_COUNT 10
+
+///
+/// A structure describing the platform configuration
+/// manager repository information
+///
+typedef struct PlatformRepositoryInfo {
+ ///
+ /// Configuration Manager Information.
+ ///
+ CM_STD_OBJ_CONFIGURATION_MANAGER_INFO CmInfo;
+
+ ///
+ /// List of ACPI tables
+ ///
+ CM_STD_OBJ_ACPI_TABLE_INFO CmAcpiTableList[PLAT_ACPI_TABLE_COUNT];
+
+ ///
+ /// Power management profile information
+ ///
+ CM_ARM_POWER_MANAGEMENT_PROFILE_INFO PmProfileInfo;
+
+ ///
+ /// ITS Group node
+ ///
+ CM_ARM_ITS_GROUP_NODE ItsGroupInfo;
+
+ ///
+ /// ITS Identifier array
+ ///
+ CM_ARM_ITS_IDENTIFIER ItsIdentifierArray[1];
+
+ ///
+ /// PCI Root complex node
+ ///
+ CM_ARM_ROOT_COMPLEX_NODE RootComplexInfo;
+
+ ///
+ /// Array of DeviceID mapping
+ ///
+ CM_ARM_ID_MAPPING DeviceIdMapping[1];
+
+ ///
+ /// Dynamic platform repository.
+ /// CmObj created by parsing the Kvmtool device tree are stored here.
+ ///
+ DYNAMIC_PLATFORM_REPOSITORY_INFO *DynamicPlatformRepo;
+
+ ///
+ /// Base address of the FDT.
+ ///
+ VOID *FdtBase;
+
+ ///
+ /// A handle to the FDT HwInfoParser.
+ ///
+ HW_INFO_PARSER_HANDLE FdtParserHandle;
+} EDKII_PLATFORM_REPOSITORY_INFO;
+
+#endif // CONFIGURATION_MANAGER_H_
diff --git a/ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManagerDxe.inf b/ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManagerDxe.inf
new file mode 100644
index 0000000000..a333966a8c
--- /dev/null
+++ b/ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManagerDxe.inf
@@ -0,0 +1,54 @@
+## @file
+# Configuration Manager Dxe
+#
+# Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = ConfigurationManagerDxe
+ FILE_GUID = 3C80D366-510C-4154-BB3A-E12439AD337C
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = ConfigurationManagerDxeInitialize
+ UNLOAD_IMAGE = ConfigurationManagerDxeUnloadImage
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = AARCH64
+#
+
+[Sources]
+ AslTables/Dsdt.asl
+ ConfigurationManager.c
+ ConfigurationManager.h
+ ConfigurationManagerDxe.inf
+
+[Packages]
+ ArmVirtPkg/ArmVirtPkg.dec
+ DynamicTablesPkg/DynamicTablesPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ DynamicPlatRepoLib
+ HobLib
+ HwInfoParserLib
+ PrintLib
+ TableHelperLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiRuntimeServicesTableLib
+
+[Protocols]
+ gEdkiiConfigurationManagerProtocolGuid
+
+[Guids]
+ gFdtHobGuid
+
+[Depex]
+ gEdkiiPlatformHasAcpiGuid