| /** @file | |
| Configuration Manager Helper Library. | |
| Copyright (c) 2025, Arm Limited. All rights reserved.<BR> | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #include <Library/BaseLib.h> | |
| #include <Library/DebugLib.h> | |
| // Module specific include files. | |
| #include <AcpiTableGenerator.h> | |
| #include <ConfigurationManagerObject.h> | |
| #include <ConfigurationManagerHelper.h> | |
| #include <MetadataHelpers.h> | |
| #include <Library/MetadataHandlerLib.h> | |
| #include <Protocol/ConfigurationManagerProtocol.h> | |
| /** | |
| This macro expands to a function that retrieves the ACPI Table list | |
| information from the Configuration Manager. | |
| */ | |
| GET_OBJECT_LIST ( | |
| EObjNameSpaceStandard, | |
| EStdObjAcpiTableList, | |
| CM_STD_OBJ_ACPI_TABLE_INFO | |
| ); | |
| /** | |
| This macro expands to a function that retrieves Proximity Domain | |
| information from the Configuration Manager. | |
| */ | |
| GET_OBJECT_LIST ( | |
| EObjNameSpaceArchCommon, | |
| EArchCommonObjProximityDomainInfo, | |
| CM_ARCH_COMMON_PROXIMITY_DOMAIN_INFO | |
| ); | |
| /** Check if an ACPI table is present in the Configuration manager's ACPI table list. | |
| @param [in] CfgMgrProtocol Pointer to the Configuration Manager | |
| Protocol Interface. | |
| @param [in] AcpiTableId Acpi Table Id. | |
| @retval TRUE if the ACPI table is in the list of ACPI tables to install. | |
| FALSE otherwise. | |
| **/ | |
| BOOLEAN | |
| EFIAPI | |
| CheckAcpiTablePresent ( | |
| IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, | |
| IN ESTD_ACPI_TABLE_ID AcpiTableId | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| CM_STD_OBJ_ACPI_TABLE_INFO *AcpiTableList; | |
| UINT32 AcpiTableListCount; | |
| UINT32 Index; | |
| Status = GetEStdObjAcpiTableList ( | |
| CfgMgrProtocol, | |
| CM_NULL_TOKEN, | |
| &AcpiTableList, | |
| &AcpiTableListCount | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| ASSERT_EFI_ERROR (Status); | |
| return FALSE; | |
| } | |
| for (Index = 0; Index < AcpiTableListCount; Index++) { | |
| if (AcpiTableList[Index].TableGeneratorId == | |
| CREATE_STD_ACPI_TABLE_GEN_ID (AcpiTableId)) | |
| { | |
| return TRUE; | |
| } | |
| } | |
| return FALSE; | |
| } | |
| /** Get a Proximity Domain Id. | |
| Proximity Domain Id are now to be placed in | |
| CM_ARCH_COMMON_PROXIMITY_DOMAIN_INFO objects rather than in the various | |
| CmObj using them. This function handles the logic in the selection | |
| of the ProximityDomainId to use. | |
| Proximity Domain Id should be preferably placed in | |
| CM_ARCH_COMMON_PROXIMITY_DOMAIN_INFO objects now. | |
| @param [in] CfgMgrProtocol Pointer to the Configuration Manager | |
| Protocol Interface. | |
| @param [in] DefaultDomainId Default per-CmObj Proximity Domain Id. | |
| The CM_ARCH_COMMON_PROXIMITY_DOMAIN_INFO | |
| should be preferably used. | |
| @param [in] Token Token referencing a | |
| CM_ARCH_COMMON_PROXIMITY_DOMAIN_INFO object. | |
| @param [out] DomainId If Success, contains DomainId to use. | |
| @retval EFI_SUCCESS Table generated successfully. | |
| @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| GetProximityDomainId ( | |
| IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CfgMgrProtocol, | |
| IN UINT32 DefaultDomainId, | |
| IN CM_OBJECT_TOKEN Token, | |
| OUT UINT32 *DomainId | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| CM_ARCH_COMMON_PROXIMITY_DOMAIN_INFO *ProximityDomain; | |
| METADATA_OBJ_PROXIMITY_DOMAIN Metadata; | |
| if ((CfgMgrProtocol == NULL) || | |
| (DomainId == NULL)) | |
| { | |
| ASSERT (CfgMgrProtocol != NULL); | |
| ASSERT (DomainId != NULL); | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| if (Token != CM_NULL_TOKEN) { | |
| Status = GetEArchCommonObjProximityDomainInfo ( | |
| CfgMgrProtocol, | |
| Token, | |
| &ProximityDomain, | |
| NULL | |
| ); | |
| } else { | |
| // If CM_NULL_TOKEN, cannot found any Proximity Domain | |
| Status = EFI_NOT_FOUND; | |
| } | |
| if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { | |
| DEBUG (( | |
| DEBUG_ERROR, | |
| "ERROR: CM_OBJ_HELPER_LIB: Failed to get Proximity Domain. Status=%r Token=%llx\n", | |
| Status, | |
| Token | |
| )); | |
| return Status; | |
| } else if ((Status == EFI_SUCCESS) && (ProximityDomain->GenerateDomainId)) { | |
| // A Proximity Domain was found and the Id must be generated. | |
| Status = MetadataHandlerGenerate ( | |
| GetMetadataRoot (), | |
| MetadataTypeProximityDomain, | |
| Token, | |
| NULL, | |
| &Metadata, | |
| sizeof (METADATA_OBJ_PROXIMITY_DOMAIN) | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| ASSERT_EFI_ERROR (Status); | |
| return Status; | |
| } | |
| *DomainId = Metadata.Id; | |
| } else { | |
| // A hard-coded DomainId is used. | |
| if (Status == EFI_NOT_FOUND) { | |
| // No ProximityDomain CmObj was found. | |
| // Use the default Id. | |
| *DomainId = DefaultDomainId; | |
| DEBUG (( | |
| DEBUG_WARN, | |
| "CM_OBJ_HELPER_LIB: Proximity Domain Ids should be described using " | |
| "the new EArchCommonObjProximityDomainInfo object. " | |
| "The field currently used will be deprecated.\n" | |
| )); | |
| } else if (!ProximityDomain->GenerateDomainId) { | |
| // A ProximityDomain CmObj was found, but generation is disabled. | |
| // Use the Domain Id. | |
| *DomainId = ProximityDomain->DomainId; | |
| Metadata.Id = *DomainId; | |
| // Add the Domain Id to the Metadata database to check duplicated values. | |
| Status = MetadataAdd ( | |
| GetMetadataRoot (), | |
| MetadataTypeProximityDomain, | |
| Token, | |
| &Metadata, | |
| sizeof (METADATA_OBJ_PROXIMITY_DOMAIN) | |
| ); | |
| if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) { | |
| ASSERT_EFI_ERROR (Status); | |
| return Status; | |
| } | |
| } else { | |
| ASSERT_EFI_ERROR (Status); | |
| } | |
| } | |
| return EFI_SUCCESS; | |
| } |