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