This commit is contained in:
Abdul Lateef Attar 2026-08-26 22:25:29 +00:00 committed by GitHub
commit b1659fc9d9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 1781 additions and 2 deletions

View file

@ -2,7 +2,7 @@
# Dsc include file for Dynamic Tables Framework.
#
# Copyright (c) 2017 - 2026, Arm Limited. All rights reserved.<BR>
# Copyright (C) 2024 - 2025 Advanced Micro Devices, Inc. All rights reserved.<BR>
# Copyright (C) 2024 - 2026 Advanced Micro Devices, Inc. All rights reserved.<BR>
# Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
@ -41,6 +41,7 @@
DynamicTablesPkg/Library/Acpi/Common/AcpiFadtLib/AcpiFadtLib.inf
DynamicTablesPkg/Library/Acpi/Common/AcpiHmatLib/AcpiHmatLib.inf
DynamicTablesPkg/Library/Acpi/Common/AcpiMcfgLib/AcpiMcfgLib.inf
DynamicTablesPkg/Library/Acpi/Common/AcpiMsctLib/AcpiMsctLib.inf
DynamicTablesPkg/Library/Acpi/Common/AcpiPcctLib/AcpiPcctLib.inf
DynamicTablesPkg/Library/Acpi/Common/AcpiPpttLib/AcpiPpttLib.inf
DynamicTablesPkg/Library/Acpi/Common/AcpiRawLib/AcpiRawLib.inf
@ -105,6 +106,7 @@
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/AcpiCedtLib.inf
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiFadtLib/AcpiFadtLib.inf
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiMcfgLib/AcpiMcfgLib.inf
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiMsctLib/AcpiMsctLib.inf
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiSlitLib/AcpiSlitLib.inf
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiSpcrLib/AcpiSpcrLib.inf
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiSpmiLib/AcpiSpmiLib.inf
@ -148,6 +150,7 @@
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiFadtLib/AcpiFadtLib.inf
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiHmatLib/AcpiHmatLib.inf
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiMcfgLib/AcpiMcfgLib.inf
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiMsctLib/AcpiMsctLib.inf
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiPcctLib/AcpiPcctLib.inf
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiPpttLib/AcpiPpttLib.inf
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiRawLib/AcpiRawLib.inf

View file

@ -3,7 +3,7 @@
#
# Copyright (c) 2019, Linaro Limited. All rights reserved.<BR>
# Copyright (c) 2019 - 2022, Arm Limited. All rights reserved.<BR>
# Copyright (C) 2024 - 2025 Advanced Micro Devices, Inc. All rights reserved.<BR>
# Copyright (C) 2024 - 2026 Advanced Micro Devices, Inc. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@ -32,6 +32,7 @@
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
SortLib|MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
UefiLib|MdePkg/Library/UefiLib/UefiLib.inf

View file

@ -91,6 +91,9 @@ The Dynamic Tables Framework implements the following ACPI table generators:
Configuration Manager and builds the HEST table.
- EINJ : The EINJ generator collates the required platform information from
the Configuration Manager and builds the EINJ table.
- MSCT : The MSCT (Maximum System Characteristics Table) generator collates
the Maximum System Characteristics information from the
Configuration Manager and builds the MSCT table.
*/
/** The ACPI_TABLE_GENERATOR_ID type describes ACPI table generator ID.
@ -133,6 +136,7 @@ typedef enum StdAcpiTableId {
EStdAcpiTableIdHest, ///< Hest Generator
EStdAcpiTableIdEinj, ///< EINJ Generator
EStdAcpiTableIdHmat, ///< HMAT Generator
EStdAcpiTableIdMsct, ///< MSCT Generator
EStdAcpiTableIdMax
} ESTD_ACPI_TABLE_ID;

View file

@ -131,6 +131,7 @@ typedef enum ArchCommonObjectID {
EArchCommonObjEnclosureElement, ///< 72 - System Enclosure Contained Element
EArchCommonObjBaseboardInfo, ///< 73 - Baseboard Info
EArchCommonObjBaseboardContainedObject, ///< 74 - Baseboard Contained Object
EArchCommonObjMsctMaxPhysicalAddrInfo, ///< 75 - MSCT Maximum physical address Info
EArchCommonObjMax
} EARCH_COMMON_OBJECT_ID;
@ -1906,6 +1907,16 @@ typedef struct CmArchCommonSystemEnclosureInfo {
UINT8 RackHeight;
} CM_ARCH_COMMON_SYSTEM_ENCLOSURE_INFO;
/** A structure that describes the Maximum Physical Address Information
for the MSCT (Maximum System Characteristics Table).
ID: EArchCommonObjMsctMaxPhysicalAddrInfo
*/
typedef struct CmArchCommonObjMsctMaxPhysicalAddrInfo {
/// Maximum Physical Address
UINT64 MaxPhysicalAddress;
} CM_ARCH_COMMON_MSCT_MAX_PHYSICAL_ADDR_INFO;
/** A structure that identifies an SMBIOS object contained by a Baseboard.
SMBIOS Specification v3.9.0 Type 2

View file

@ -0,0 +1,44 @@
## @file
# ACPI Maximum System Characteristics Table (MSCT) Generator
#
# Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
[Defines]
INF_VERSION = 1.30
BASE_NAME = AcpiMsctLib
FILE_GUID = D4F5A6B7-C8D9-4E0A-B1C2-3D4E5F607182
VERSION_STRING = 1.0
MODULE_TYPE = DXE_DRIVER
LIBRARY_CLASS = NULL|DXE_DRIVER
CONSTRUCTOR = AcpiMsctLibConstructor
DESTRUCTOR = AcpiMsctLibDestructor
[Sources]
MsctGenerator.c
MsctGenerator.h
[Sources.x64]
X64/X64MsctGenerator.c
[Sources.AARCH64]
Arm/ArmMsctGenerator.c
[Sources.RISCV64]
Default/DefaultMsctGenerator.c
[Sources.LOONGARCH64]
Default/DefaultMsctGenerator.c
[Packages]
DynamicTablesPkg/DynamicTablesPkg.dec
MdeModulePkg/MdeModulePkg.dec
MdePkg/MdePkg.dec
[LibraryClasses]
BaseLib
CmObjHelperLib
SortLib

View file

@ -0,0 +1,249 @@
/** @file
ARM specific ACPI Maximum System Characteristics Table (MSCT) Generator
Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
// Module specific include files.
#include <AcpiTableGenerator.h>
#include <ConfigurationManagerObject.h>
#include <ConfigurationManagerHelper.h>
#include <Library/TableHelperLib.h>
#include <Protocol/ConfigurationManagerProtocol.h>
#include <Library/CmObjHelperLib.h>
#include "MsctGenerator.h"
/**
ARM standard MSCT Generator
Requirements:
The following Configuration Manager Object(s) are used by this Generator:
- EArmObjGicCInfo (OPTIONAL)
*/
/** This macro expands to a function that retrieves the GIC
CPU interface Information from the Configuration Manager.
*/
GET_OBJECT_LIST (
EObjNameSpaceArm,
EArmObjGicCInfo,
CM_ARM_GICC_INFO
);
/** Get architecture processor domain information.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol.
@param [out] ProcDomainInfo Pointer to the processor domain information.
@param [out] ProcDomainInfoCount Pointer to the count of processor domain
information structures.
@retval EFI_SUCCESS Operation completed successfully.
@retval EFI_INVALID_PARAMETER A parameter is invalid.
@retval EFI_OUT_OF_RESOURCES Memory allocation failed.
@retval Other Other EFI_STATUS error from called functions.
**/
EFI_STATUS
EFIAPI
GetArchProcessorDomainInfo (
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
OUT UINT32 **ProcDomainInfo,
OUT UINT32 *ProcDomainInfoCount
)
{
CM_ARM_GICC_INFO *CmProcDomain;
EFI_STATUS Status;
UINT32 Index;
UINT32 ProcDomainCount;
UINT32 *ProcDomain;
if ((CfgMgrProtocol == NULL) ||
(ProcDomainInfo == NULL) ||
(ProcDomainInfoCount == NULL))
{
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
return EFI_INVALID_PARAMETER;
}
CmProcDomain = NULL;
ProcDomain = NULL;
ProcDomainCount = 0;
Status = GetEArmObjGicCInfo (
CfgMgrProtocol,
CM_NULL_TOKEN,
&CmProcDomain,
&ProcDomainCount
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"ERROR: MSCT: Failed to get GICC Info. Status = %r\n",
Status
));
return Status;
}
ProcDomain = AllocateZeroPool (
sizeof (UINT32) *
ProcDomainCount
);
if (ProcDomain == NULL) {
Status = EFI_OUT_OF_RESOURCES;
ASSERT_EFI_ERROR (Status);
return Status;
}
for (Index = 0; Index < ProcDomainCount; Index++) {
Status = GetProximityDomainId (
CfgMgrProtocol,
CmProcDomain[Index].ProximityDomain,
CmProcDomain[Index].ProximityDomainToken,
&ProcDomain[Index]
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"MSCT: Failed to get Proximity Domain ID for index %d. Status = %r\n",
Index,
Status
));
ASSERT_EFI_ERROR (Status);
goto error_handler;
}
}
*ProcDomainInfo = ProcDomain;
*ProcDomainInfoCount = ProcDomainCount;
return EFI_SUCCESS;
error_handler:
if (ProcDomain != NULL) {
FreePool (ProcDomain);
}
return Status;
}
/** Get the count of unique architecture clock domains.
Enumerates all GIC CPU interfaces and returns the number of unique clock
proximity domain IDs in the system.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol.
@param [out] ClockDomainCount On success, the cardinal count of unique
clock domains.
@retval EFI_SUCCESS Operation completed successfully.
@retval EFI_INVALID_PARAMETER A parameter is invalid.
@retval EFI_OUT_OF_RESOURCES Memory allocation failed.
@retval Other Other EFI_STATUS error from called functions.
**/
EFI_STATUS
EFIAPI
GetArchClockDomainInfo (
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
OUT UINT32 *ClockDomainCount
)
{
EFI_STATUS Status;
UINT32 ProximityDomain;
UINT32 CmCount;
UINT32 Index;
UINT32 UniqueIndex;
CM_ARM_GICC_INFO *CmGiccInfo;
UINT32 *ClockDomains;
UINT32 UniqueCount;
BOOLEAN IsUnique;
if ((CfgMgrProtocol == NULL) ||
(ClockDomainCount == NULL))
{
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
return EFI_INVALID_PARAMETER;
}
CmGiccInfo = NULL;
ClockDomains = NULL;
UniqueCount = 0;
CmCount = 0;
Status = GetEArmObjGicCInfo (
CfgMgrProtocol,
CM_NULL_TOKEN,
&CmGiccInfo,
&CmCount
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"ERROR: MSCT: Failed to get GICC Info. Status = %r\n",
Status
));
return Status;
}
if ((CmGiccInfo == NULL) || (CmCount == 0)) {
*ClockDomainCount = 0;
return EFI_SUCCESS;
}
// Allocate worst-case storage: every CPU could be in its own clock domain.
ClockDomains = AllocateZeroPool (sizeof (UINT32) * CmCount);
if (ClockDomains == NULL) {
Status = EFI_OUT_OF_RESOURCES;
ASSERT_EFI_ERROR (Status);
return Status;
}
for (Index = 0; Index < CmCount; Index++) {
Status = GetProximityDomainId (
CfgMgrProtocol,
CmGiccInfo[Index].ClockDomain,
CmGiccInfo[Index].ClockDomainToken,
&ProximityDomain
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"ERROR: MSCT: Failed to get Clock Domain ID for index %d. Status = %r\n",
Index,
Status
));
ASSERT_EFI_ERROR (Status);
goto error_handler;
}
// Record the proximity domain ID only if not already seen.
IsUnique = TRUE;
for (UniqueIndex = 0; UniqueIndex < UniqueCount; UniqueIndex++) {
if (ClockDomains[UniqueIndex] == ProximityDomain) {
IsUnique = FALSE;
break;
}
}
if (IsUnique) {
ClockDomains[UniqueCount++] = ProximityDomain;
}
}
*ClockDomainCount = UniqueCount;
Status = EFI_SUCCESS;
error_handler:
if (ClockDomains != NULL) {
FreePool (ClockDomains);
}
return Status;
}

View file

@ -0,0 +1,67 @@
/** @file
Default (stub) arch-specific ACPI MSCT Generator implementation.
Used for architectures that do not provide processor or clock domain
information via the Configuration Manager (e.g. RISCV64, LOONGARCH64).
Both functions return EFI_NOT_FOUND so that the common generator
gracefully omits the arch-specific topology data from the MSCT.
Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Library/DebugLib.h>
// Module specific include files.
#include <AcpiTableGenerator.h>
#include <ConfigurationManagerObject.h>
#include <Protocol/ConfigurationManagerProtocol.h>
#include "MsctGenerator.h"
/** Get architecture processor domain information.
This stub implementation returns EFI_NOT_FOUND for architectures that
do not provide processor proximity domain data via the Configuration Manager.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol.
@param [out] ProcDomainInfo Pointer to the processor domain information.
@param [out] ProcDomainInfoCount Pointer to the count of processor domain
information structures.
@retval EFI_NOT_FOUND Not supported on this architecture.
**/
EFI_STATUS
EFIAPI
GetArchProcessorDomainInfo (
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
OUT UINT32 **ProcDomainInfo,
OUT UINT32 *ProcDomainInfoCount
)
{
return EFI_NOT_FOUND;
}
/** Get the count of unique architecture clock domains.
This stub implementation returns EFI_NOT_FOUND for architectures that
do not provide clock domain data via the Configuration Manager.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol.
@param [out] ClockDomainCount On success, the cardinal count of unique
clock domains.
@retval EFI_NOT_FOUND Not supported on this architecture.
**/
EFI_STATUS
EFIAPI
GetArchClockDomainInfo (
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
OUT UINT32 *ClockDomainCount
)
{
return EFI_NOT_FOUND;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,52 @@
/** @file
ACPI Maximum System Characteristics Table (MSCT) Generator header file.
Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#pragma once
/** Get architecture processor domain information.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol.
@param [out] ProcDomainInfo Pointer to the processor domain information.
@param [out] ProcDomainInfoCount Pointer to the count of processor domain
information structures.
@retval EFI_SUCCESS Operation completed successfully.
@retval EFI_INVALID_PARAMETER A parameter is invalid.
@retval EFI_OUT_OF_RESOURCES Memory allocation failed.
@retval Other Other EFI_STATUS error from called functions.
**/
EFI_STATUS
EFIAPI
GetArchProcessorDomainInfo (
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
OUT UINT32 **ProcDomainInfo,
OUT UINT32 *ProcDomainInfoCount
);
/** Get the count of unique architecture clock domains.
Enumerates all CPU interfaces and returns the number of unique clock
proximity domain IDs in the system.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol.
@param [out] ClockDomainCount On success, the cardinal count of unique
clock domains.
@retval EFI_SUCCESS Operation completed successfully.
@retval EFI_INVALID_PARAMETER A parameter is invalid.
@retval EFI_OUT_OF_RESOURCES Memory allocation failed.
@retval Other Other EFI_STATUS error from called functions.
**/
EFI_STATUS
EFIAPI
GetArchClockDomainInfo (
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
OUT UINT32 *ClockDomainCount
);

View file

@ -0,0 +1,249 @@
/** @file
X64 specific ACPI Maximum System Characteristics Table (MSCT) Generator
Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
// Module specific include files.
#include <AcpiTableGenerator.h>
#include <ConfigurationManagerObject.h>
#include <ConfigurationManagerHelper.h>
#include <Library/TableHelperLib.h>
#include <Protocol/ConfigurationManagerProtocol.h>
#include <Library/CmObjHelperLib.h>
#include "MsctGenerator.h"
/**
This macro is used to get the object information for the Local APIC X2APIC
Affinity object.
*/
GET_OBJECT_LIST (
EObjNameSpaceX64,
EX64ObjLocalApicX2ApicAffinityInfo,
CM_X64_LOCAL_APIC_X2APIC_AFFINITY_INFO
);
/** Get architecture processor domain information.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol.
@param [out] ProcDomainInfo Pointer to the processor domain information.
@param [out] ProcDomainInfoCount Pointer to the count of processor domain
information structures.
@retval EFI_SUCCESS Operation completed successfully.
@retval EFI_INVALID_PARAMETER A parameter is invalid.
@retval EFI_OUT_OF_RESOURCES Memory allocation failed.
@retval Other Other EFI_STATUS error from called functions.
**/
EFI_STATUS
EFIAPI
GetArchProcessorDomainInfo (
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
OUT UINT32 **ProcDomainInfo,
OUT UINT32 *ProcDomainInfoCount
)
{
CM_X64_LOCAL_APIC_X2APIC_AFFINITY_INFO *CmProcDomain;
EFI_STATUS Status;
UINT32 Index;
UINT32 ProcDomainCount;
UINT32 *ProcDomain;
if ((CfgMgrProtocol == NULL) ||
(ProcDomainInfo == NULL) ||
(ProcDomainInfoCount == NULL))
{
return EFI_INVALID_PARAMETER;
}
CmProcDomain = NULL;
ProcDomain = NULL;
ProcDomainCount = 0;
Status = GetEX64ObjLocalApicX2ApicAffinityInfo (
CfgMgrProtocol,
CM_NULL_TOKEN,
&CmProcDomain,
&ProcDomainCount
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"MSCT: Failed to get processor affinity information. Status = %r\n",
Status
));
goto error_handler;
}
if ((ProcDomainCount == 0) || (CmProcDomain == NULL)) {
DEBUG ((
DEBUG_ERROR,
"MSCT: No Local Apic/X2Apic Affinity information found.\n"
));
Status = EFI_NOT_FOUND;
goto error_handler;
}
ProcDomain = AllocateZeroPool (
sizeof (UINT32) *
ProcDomainCount
);
if (ProcDomain == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto error_handler;
}
for (Index = 0; Index < ProcDomainCount; Index++) {
Status = GetProximityDomainId (
CfgMgrProtocol,
CmProcDomain[Index].ProximityDomain,
CmProcDomain[Index].ProximityDomainToken,
&ProcDomain[Index]
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"MSCT: Failed to get Proximity Domain ID for index %d. Status = %r\n",
Index,
Status
));
goto error_handler;
}
}
*ProcDomainInfo = ProcDomain;
*ProcDomainInfoCount = ProcDomainCount;
return EFI_SUCCESS;
error_handler:
if (ProcDomain != NULL) {
FreePool (ProcDomain);
}
return Status;
}
/** Get the count of unique architecture clock domains.
Enumerates all Local APIC/X2APIC affinity entries and returns the number of
unique clock proximity domain IDs in the system.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol.
@param [out] ClockDomainCount On success, the cardinal count of unique
clock domains.
@retval EFI_SUCCESS Operation completed successfully.
@retval EFI_INVALID_PARAMETER A parameter is invalid.
@retval EFI_NOT_FOUND No affinity information was found.
@retval EFI_OUT_OF_RESOURCES Memory allocation failed.
@retval Other Other EFI_STATUS error from called functions.
**/
EFI_STATUS
EFIAPI
GetArchClockDomainInfo (
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
OUT UINT32 *ClockDomainCount
)
{
EFI_STATUS Status;
UINT32 ProximityDomain;
UINT32 CmCount;
UINT32 Index;
UINT32 UniqueIndex;
UINT32 UniqueCount;
UINT32 *ClockDomains;
BOOLEAN IsUnique;
CM_X64_LOCAL_APIC_X2APIC_AFFINITY_INFO *CmX2ApicAffinity;
if ((CfgMgrProtocol == NULL) ||
(ClockDomainCount == NULL))
{
return EFI_INVALID_PARAMETER;
}
CmX2ApicAffinity = NULL;
ClockDomains = NULL;
UniqueCount = 0;
CmCount = 0;
Status = GetEX64ObjLocalApicX2ApicAffinityInfo (
CfgMgrProtocol,
CM_NULL_TOKEN,
&CmX2ApicAffinity,
&CmCount
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"ERROR: MSCT: Failed to get Local Apic/X2Apic Affinity Info. Status = %r\n",
Status
));
return Status;
}
if ((CmX2ApicAffinity == NULL) || (CmCount == 0)) {
DEBUG ((
DEBUG_ERROR,
"ERROR: MSCT: Local Apic/X2Apic Affinity information not provided.\n"
));
return EFI_NOT_FOUND;
}
// Allocate worst-case storage: every CPU could be in its own clock domain.
ClockDomains = AllocateZeroPool (sizeof (UINT32) * CmCount);
if (ClockDomains == NULL) {
Status = EFI_OUT_OF_RESOURCES;
ASSERT_EFI_ERROR (Status);
return Status;
}
for (Index = 0; Index < CmCount; Index++) {
Status = GetProximityDomainId (
CfgMgrProtocol,
CmX2ApicAffinity[Index].ClockDomain,
CmX2ApicAffinity[Index].ClockDomainToken,
&ProximityDomain
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"ERROR: MSCT: Failed to get Clock Domain ID for index %d. Status = %r\n",
Index,
Status
));
ASSERT_EFI_ERROR (Status);
goto error_handler;
}
// Record the proximity domain ID only if not already seen.
IsUnique = TRUE;
for (UniqueIndex = 0; UniqueIndex < UniqueCount; UniqueIndex++) {
if (ClockDomains[UniqueIndex] == ProximityDomain) {
IsUnique = FALSE;
break;
}
}
if (IsUnique) {
ClockDomains[UniqueCount++] = ProximityDomain;
}
}
*ClockDomainCount = UniqueCount;
Status = EFI_SUCCESS;
error_handler:
if (ClockDomains != NULL) {
FreePool (ClockDomains);
}
return Status;
}

View file

@ -1398,6 +1398,12 @@ STATIC CONST CM_OBJ_PARSER CmArchCommonEnclosureElementParser[] = {
{ "ContainedElementMaximum", sizeof (UINT8), "%u", NULL },
};
/** A parser for EArchCommonObjMsctMaxPhysicalAddrInfo.
*/
STATIC CONST CM_OBJ_PARSER CmArchCommonMsctMaxPhysicalAddrInfoParser[] = {
{ "MaxPhysicalAddress", 8, "0x%llx", NULL }
};
/** A parser for EArchCommonObjBaseboardContainedObject.
*/
STATIC CONST CM_OBJ_PARSER CmArchCommonBaseboardContainedObjectParser[] = {
@ -1500,6 +1506,7 @@ STATIC CONST CM_OBJ_PARSER_ARRAY ArchCommonNamespaceObjectParser[] = {
CM_PARSER_ADD_OBJECT (EArchCommonObjEnclosureElement, CmArchCommonEnclosureElementParser),
CM_PARSER_ADD_OBJECT (EArchCommonObjBaseboardInfo, CmArchCommonBaseboardInfoParser),
CM_PARSER_ADD_OBJECT (EArchCommonObjBaseboardContainedObject, CmArchCommonBaseboardContainedObjectParser),
CM_PARSER_ADD_OBJECT (EArchCommonObjMsctMaxPhysicalAddrInfo, CmArchCommonMsctMaxPhysicalAddrInfoParser),
CM_PARSER_ADD_OBJECT_RESERVED (EArchCommonObjMax)
};