DynamicTablesPkg: Generalize the CMN SSDT generator

Extend the CMN Configuration Manager object with an implementation type
and optional root-node region length.

Map the implementation type to the ACPI hardware IDs for CMN-600,
CMN-650, CMN-700 and CMN-S3. Apply CMN-600-specific address restrictions
only when the CMN-600 implementation type is selected.

Rename the CMN-600 generator, identifiers and files to reflect support
for multiple CMN implementations.

Signed-off-by: Varshit Pandya <varshit.pandya@arm.com>
This commit is contained in:
Varshit Pandya 2026-08-17 16:00:30 +01:00 committed by VarshitPandya
parent cc9a0425a2
commit 9c5eb0687d
11 changed files with 368 additions and 262 deletions

View file

@ -132,7 +132,7 @@
DynamicTablesPkg/Library/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf
# AML Fixup (Arm specific)
DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600LibArm.inf
DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmnLibArm/SsdtCmnLibArm.inf
DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtDmc620PmuLibArm/SsdtDmc620PmuLibArm.inf
@ -167,7 +167,7 @@
# Common
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtSerialPortLib/SsdtSerialPortLib.inf
# Arm specific
NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600LibArm.inf
NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmnLibArm/SsdtCmnLibArm.inf
NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtDmc620PmuLibArm/SsdtDmc620PmuLibArm.inf
# AML Codegen

View file

@ -60,10 +60,10 @@ The Dynamic Tables Framework implements the following ACPI table generators:
The SSDT Serial generator collates the Serial port information
from the Configuration Manager and patches the SSDT Serial Port
template to build the SSDT Serial port table.
- SSDT CMN-600:
The SSDT CMN-600 generator collates the CMN-600 information
from the Configuration Manager and patches the SSDT CMN-600
template to build the SSDT CMN-600 table.
- SSDT CMN:
The SSDT CMN generator collates the CMN information
from the Configuration Manager and patches the SSDT CMN
template to build the SSDT CMN table.
- SSDT Cpu-Topology:
The SSDT Cpu-Topology generator collates the cpu and LPI
information from the Configuration Manager and generates a
@ -115,7 +115,7 @@ typedef enum StdAcpiTableId {
EStdAcpiTableIdPptt, ///< PPTT Generator
EStdAcpiTableIdSrat, ///< SRAT Generator
EStdAcpiTableIdSsdtSerialPort, ///< SSDT Serial-Port Generator
EStdAcpiTableIdSsdtCmn600, ///< SSDT Cmn-600 Generator
EStdAcpiTableIdSsdtCmn, ///< SSDT Cmn Generator
EStdAcpiTableIdSsdtCpuTopology, ///< SSDT Cpu Topology
EStdAcpiTableIdSsdtPciExpress, ///< SSDT Pci Express Generator
EStdAcpiTableIdSsdtPlicAplic, ///< SSDT Plic/Aplic Generator

View file

@ -1,6 +1,6 @@
/** @file
Copyright (c) 2017 - 2024, Arm Limited. All rights reserved.<BR>
Copyright (c) 2017 - 2026, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@ -47,7 +47,7 @@ typedef enum ArmObjectID {
EArmObjGicItsIdentifierArray, ///< 17 - GIC ITS Identifier Array
EArmObjIdMappingArray, ///< 18 - ID Mapping Array
EArmObjSmmuInterruptArray, ///< 19 - SMMU Interrupt Array
EArmObjCmn600Info, ///< 20 - CMN-600 Info
EArmObjCmnInfo, ///< 20 - CMN Info
EArmObjRmr, ///< 21 - Reserved Memory Range Node
EArmObjMemoryRangeDescriptor, ///< 22 - Memory Range Descriptor
EArmObjEtInfo, ///< 23 - Embedded Trace Extension/Module Info
@ -662,37 +662,47 @@ typedef CM_ARCH_COMMON_GENERIC_INTERRUPT CM_ARM_SMMU_INTERRUPT;
*/
typedef CM_ARCH_COMMON_GENERIC_INTERRUPT CM_ARM_EXTENDED_INTERRUPT;
/** A structure that describes the CMN-600 hardware.
/** CMN implementation types. */
typedef enum ArmCmnType {
ArmCmnType600,
ArmCmnType650,
ArmCmnType700,
ArmCmnTypeS3,
ArmCmnTypeMax
} ARM_CMN_TYPE;
ID: EArmObjCmn600Info
/** A structure that describes CMN hardware.
ID: EArmObjCmnInfo
*/
typedef struct CmArmCmn600Info {
typedef struct CmArmCmnInfo {
/// The PERIPHBASE address.
/// Corresponds to the Configuration Node Region (CFGR) base address.
UINT64 PeriphBaseAddress;
UINT64 PeriphBaseAddress;
/// The PERIPHBASE address length.
/// Corresponds to the CFGR base address length.
UINT64 PeriphBaseAddressLength;
UINT64 PeriphBaseAddressLength;
/// The ROOTNODEBASE address.
/// Corresponds to the Root node (ROOT) base address.
UINT64 RootNodeBaseAddress;
UINT64 RootNodeBaseAddress;
/// The Debug and Trace Logic Controller (DTC) count.
/// CMN-600 can have maximum 4 DTCs.
UINT8 DtcCount;
/// Number of Debug and Trace Logic Controller interrupts.
/// A maximum of four DTC interrupts can be described.
UINT8 DtcCount;
/// DTC Interrupt list.
/// The first interrupt resource descriptor pertains to
/// DTC[0], the second to DTC[1] and so on.
/// DtcCount determines the number of DTC Interrupts that
/// are populated. If DTC count is 2 then DtcInterrupt[2]
/// and DtcInterrupt[3] are ignored.
/// Note: The size of CM_ARM_CMN_600_INFO structure remains
/// constant and does not vary with the DTC count.
/// DTC interrupt descriptors.
/// Entries must be ordered by increasing hardware-assigned DTC Logical ID.
/// DtcCount determines the number of valid entries.
CM_ARM_EXTENDED_INTERRUPT DtcInterrupt[4];
} CM_ARM_CMN_600_INFO;
/// CMN implementation type.
ARM_CMN_TYPE CmnType;
/// Length of the optional root-node region. Zero means no ROOT resource.
UINT64 RootNodeBaseAddressLength;
} CM_ARM_CMN_INFO;
/** A structure that describes the DMC620 PMU hardware
registers and interrupt.

View file

@ -1,48 +0,0 @@
/** @file
Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Glossary:
- Cm or CM - Configuration Manager
- Obj or OBJ - Object
- Std or STD - Standard
@par Reference(s):
- Arm CoreLink CMN-600 Coherent Mesh Network Technical Reference Manual r3p0
- Generic ACPI for Arm Components 1.0 Platform Design Document
**/
#pragma once
/** PeriphBase maximum address length is 256MB (0x10000000)
for a (X >= 4) || (Y >= 4) dimensions mesh.
*/
#define PERIPHBASE_MAX_ADDRESS_LENGTH SIZE_256MB
/** PeriphBase minimum address length is 64MB (0x04000000)
for a (X < 4) && (Y < 4) dimensions mesh.
*/
#define PERIPHBASE_MIN_ADDRESS_LENGTH SIZE_64MB
/** RootNodeBase address length is 16KB (0x00004000).
*/
#define ROOTNODEBASE_ADDRESS_LENGTH SIZE_16KB
/** Maximum number of CMN-600 Debug and Trace Logic Controllers (DTC).
*/
#define MAX_DTC_COUNT 4
/** Starting value for the UID to represent the CMN600 devices.
*/
#define CMN600_DEVICE_START_UID 0
/** Maximum CMN-600 devices supported by this generator.
This generator supports a maximum of 16 CMN-600 devices.
Note: This is not a hard limitation and can be extended if needed.
Corresponding changes would be needed to support the Name and
UID fields describing the serial port.
*/
#define MAX_CMN600_DEVICES_SUPPORTED 16

View file

@ -1,13 +1,13 @@
/** @file
SSDT CMN-600 AML Table Generator.
SSDT CMN AML Table Generator.
Copyright (c) 2020 - 2021, Arm Limited. All rights reserved.<BR>
Copyright (c) 2020 - 2026, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Reference(s):
- Arm CoreLink CMN-600 Coherent Mesh Network Technical Reference Manual r3p0
- Generic ACPI for Arm Components 1.0 Platform Design Document
- Generic ACPI for Arm Components 1.3 Platform Design Document
**/
#include <Library/AcpiLib.h>
@ -24,35 +24,76 @@
#include <Library/AcpiHelperLib.h>
#include <Library/AmlLib/AmlLib.h>
#include <Protocol/ConfigurationManagerProtocol.h>
#include "SsdtCmn600Generator.h"
#include "SsdtCmnGenerator.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 ssdtcmn600template_aml_code[];
extern CHAR8 ssdtcmntemplate_aml_code[];
/** SSDT CMN-600 Table Generator.
/** SSDT CMN Table Generator.
Requirements:
The following Configuration Manager Object(s) are required by
this Generator:
- EArmObjCmn600Info
- EArmObjCmnInfo
*/
/** This macro expands to a function that retrieves the CMN-600
/** This macro expands to a function that retrieves the CMN
Information from the Configuration Manager.
*/
GET_OBJECT_LIST (
EObjNameSpaceArm,
EArmObjCmn600Info,
CM_ARM_CMN_600_INFO
EArmObjCmnInfo,
CM_ARM_CMN_INFO
);
/** Check the CMN-600 Information.
/** Get the ACPI Hardware ID for a CMN implementation. */
STATIC
CONST CHAR8 *
GetCmnHid (
IN ARM_CMN_TYPE CmnType
)
{
switch (CmnType) {
case ArmCmnType600:
return ACPI_HID_CMN_600;
@param [in] Cmn600InfoList Array of CMN-600 information structure.
@param [in] Cmn600Count Count of CMN-600 information structure.
case ArmCmnType650:
return ACPI_HID_CMN_650;
case ArmCmnType700:
return ACPI_HID_CMN_700;
case ArmCmnTypeS3:
return ACPI_HID_CMN_S3;
default:
return NULL;
}
}
/** Return TRUE if the CMN object describes a ROOT resource.
@param [in] CmnInfo CMN information structure.
@retval TRUE The CMN object describes a ROOT resource.
@retval FALSE The CMN object does not describe a ROOT resource.
**/
STATIC
BOOLEAN
HasCmnRootNode (
IN CONST CM_ARM_CMN_INFO *CmnInfo
)
{
return CmnInfo->RootNodeBaseAddressLength != 0;
}
/** Check the CMN information.
@param [in] CmnInfoList Array of CMN information structure.
@param [in] CmnCount Count of CMN information structure.
@retval EFI_SUCCESS The function completed successfully.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@ -60,109 +101,132 @@ GET_OBJECT_LIST (
STATIC
EFI_STATUS
EFIAPI
ValidateCmn600Info (
IN CONST CM_ARM_CMN_600_INFO *Cmn600InfoList,
IN CONST UINT32 Cmn600Count
ValidateCmnInfo (
IN CONST CM_ARM_CMN_INFO *CmnInfoList,
IN CONST UINT32 CmnCount
)
{
UINT32 Index;
UINT32 DtcIndex;
CONST CM_ARM_CMN_600_INFO *Cmn600Info;
CONST CM_ARM_CMN_INFO *CmnInfo;
CONST CM_ARCH_COMMON_GENERIC_INTERRUPT *DtcInterrupt;
if ((Cmn600InfoList == NULL) ||
(Cmn600Count == 0))
if ((CmnInfoList == NULL) ||
(CmnCount == 0))
{
return EFI_INVALID_PARAMETER;
}
// Validate each Cmn600Info structure.
for (Index = 0; Index < Cmn600Count; Index++) {
Cmn600Info = &Cmn600InfoList[Index];
// Validate each CmnInfo structure.
for (Index = 0; Index < CmnCount; Index++) {
CmnInfo = &CmnInfoList[Index];
// At least one DTC is required.
if ((Cmn600Info->DtcCount == 0) ||
(Cmn600Info->DtcCount > MAX_DTC_COUNT))
// Validate the CMN configuration region.
if ((CmnInfo->PeriphBaseAddressLength == 0) ||
((CmnInfo->PeriphBaseAddressLength - 1) >
(MAX_UINT64 - CmnInfo->PeriphBaseAddress)))
{
DEBUG ((
DEBUG_ERROR,
"ERROR: SSDT-CMN-600: Invalid DTC configuration:\n"
"ERROR: SSDT-CMN: Invalid configuration region.\n"
));
goto error_handler;
}
// Check PERIPHBASE and ROOTNODEBASE address spaces are initialized.
if ((Cmn600Info->PeriphBaseAddress == 0) ||
(Cmn600Info->RootNodeBaseAddress == 0))
if ((CmnInfo->PeriphBaseAddress &
(CMN_PERIPHBASE_ADDRESS_ALIGNMENT - 1)) != 0)
{
DEBUG ((
DEBUG_ERROR,
"ERROR: SSDT-CMN-600: Invalid PERIPHBASE or ROOTNODEBASE.\n"
"ERROR: SSDT-CMN: CMN configuration base must be "
"64 MB aligned.\n"
));
goto error_handler;
}
// The PERIPHBASE address must be 64MB aligned for a (X < 4) && (Y < 4)
// dimension mesh, and 256MB aligned otherwise.
// Check it is a least 64MB aligned.
if ((Cmn600Info->PeriphBaseAddress &
(PERIPHBASE_MIN_ADDRESS_LENGTH - 1)) != 0)
if (GetCmnHid (CmnInfo->CmnType) == NULL) {
DEBUG ((
DEBUG_ERROR,
"ERROR: SSDT-CMN: Invalid CMN implementation type.\n"
));
goto error_handler;
}
if ((CmnInfo->DtcCount == 0) ||
(CmnInfo->DtcCount > MAX_CMN_DTC_COUNT))
{
DEBUG ((
DEBUG_ERROR,
"ERROR: SSDT-CMN-600: PERIPHBASE address must be 64MB aligned.\n"
"ERROR: SSDT-CMN: Invalid DTC count.\n"
));
goto error_handler;
}
// The PERIPHBASE address is at most 64MB for a (X < 4) && (Y < 4)
// dimension mesh, and 256MB otherwise. Check it is not more than 256MB.
if (Cmn600Info->PeriphBaseAddressLength > PERIPHBASE_MAX_ADDRESS_LENGTH) {
DEBUG ((
DEBUG_ERROR,
"ERROR: SSDT-CMN-600: PERIPHBASE address range must be < 256MB.\n"
));
goto error_handler;
}
if (CmnInfo->CmnType == ArmCmnType600) {
if (!HasCmnRootNode (CmnInfo) ||
(CmnInfo->RootNodeBaseAddressLength !=
CMN600_ROOTNODEBASE_ADDRESS_LENGTH) ||
((CmnInfo->RootNodeBaseAddress &
(CMN600_ROOTNODEBASE_ADDRESS_LENGTH - 1)) != 0) ||
((CmnInfo->RootNodeBaseAddressLength - 1) >
(MAX_UINT64 - CmnInfo->RootNodeBaseAddress)))
{
DEBUG ((
DEBUG_ERROR,
"ERROR: SSDT-CMN: Invalid CMN-600 ROOT region.\n"
));
goto error_handler;
}
// Check the 16 KB alignment of the ROOTNODEBASE address.
if ((Cmn600Info->PeriphBaseAddress &
(ROOTNODEBASE_ADDRESS_LENGTH - 1)) != 0)
if ((CmnInfo->RootNodeBaseAddress < CmnInfo->PeriphBaseAddress) ||
(CmnInfo->RootNodeBaseAddressLength >
CmnInfo->PeriphBaseAddressLength) ||
((CmnInfo->RootNodeBaseAddress -
CmnInfo->PeriphBaseAddress) >
(CmnInfo->PeriphBaseAddressLength -
CmnInfo->RootNodeBaseAddressLength)))
{
DEBUG ((
DEBUG_ERROR,
"ERROR: SSDT-CMN: ROOT region is outside the "
"configuration region.\n"
));
goto error_handler;
}
if (CmnInfo->PeriphBaseAddressLength >
CMN600_PERIPHBASE_MAX_ADDRESS_LENGTH)
{
DEBUG ((
DEBUG_ERROR,
"ERROR: SSDT-CMN: CMN configuration region exceeds "
"256 MB.\n"
));
goto error_handler;
}
} else if ((CmnInfo->RootNodeBaseAddress != 0) ||
HasCmnRootNode (CmnInfo))
{
DEBUG ((
DEBUG_ERROR,
"ERROR: SSDT-CMN-600: Root base address must be 16KB aligned.\n"
"ERROR: SSDT-CMN: ROOT region is only valid for CMN-600.\n"
));
goto error_handler;
}
// The ROOTNODEBASE address space should be included in the PERIPHBASE
// address space.
if ((Cmn600Info->PeriphBaseAddress > Cmn600Info->RootNodeBaseAddress) ||
((Cmn600Info->PeriphBaseAddress + Cmn600Info->PeriphBaseAddressLength) <
(Cmn600Info->RootNodeBaseAddress + ROOTNODEBASE_ADDRESS_LENGTH)))
{
DEBUG ((
DEBUG_ERROR,
"ERROR: SSDT-CMN-600:"
" ROOTNODEBASE address space not in PERIPHBASE address space.\n"
));
goto error_handler;
}
for (DtcIndex = 0; DtcIndex < Cmn600Info->DtcCount; DtcIndex++) {
DtcInterrupt = &Cmn600Info->DtcInterrupt[DtcIndex];
for (DtcIndex = 0; DtcIndex < CmnInfo->DtcCount; DtcIndex++) {
DtcInterrupt = &CmnInfo->DtcInterrupt[DtcIndex];
if (((DtcInterrupt->Flags &
EFI_ACPI_EXTENDED_INTERRUPT_FLAG_PRODUCER_CONSUMER_MASK) == 0))
{
DEBUG ((
DEBUG_ERROR,
"ERROR: SSDT-CMN-600: DTC Interrupt must be consumer.\n"
"ERROR: SSDT-CMN: DTC Interrupt must be consumer.\n"
));
goto error_handler;
}
} // for DTC Interrupt
} // for Cmn600InfoList
} // for CmnInfoList
return EFI_SUCCESS;
@ -174,15 +238,19 @@ error_handler:
"PeriphBaseAddressLength = 0x%llx\n"
"RootNodeBaseAddress = 0x%llx\n"
"DtcCount = %u\n",
Cmn600Info->PeriphBaseAddress,
Cmn600Info->PeriphBaseAddressLength,
Cmn600Info->RootNodeBaseAddress,
Cmn600Info->DtcCount
CmnInfo->PeriphBaseAddress,
CmnInfo->PeriphBaseAddressLength,
CmnInfo->RootNodeBaseAddress,
CmnInfo->DtcCount
));
DEBUG_CODE_BEGIN ();
for (DtcIndex = 0; DtcIndex < Cmn600Info->DtcCount; DtcIndex++) {
DtcInterrupt = &Cmn600Info->DtcInterrupt[DtcIndex];
for (DtcIndex = 0;
(DtcIndex < CmnInfo->DtcCount) &&
(DtcIndex < MAX_CMN_DTC_COUNT);
DtcIndex++)
{
DtcInterrupt = &CmnInfo->DtcInterrupt[DtcIndex];
DEBUG ((
DEBUG_ERROR,
" DTC[%d]:\n",
@ -205,15 +273,15 @@ error_handler:
return EFI_INVALID_PARAMETER;
}
/** Build a SSDT table describing the CMN-600 device.
/** Build a SSDT table describing the CMN device.
The table created by this function must be freed by FreeSsdtCmn600Table.
The table created by this function must be freed by FreeSsdtCmnTableResourcesEx.
@param [in] Cmn600Info Pointer to a Cmn600 structure.
@param [in] CmnInfo Pointer to a CMN structure.
@param [in] Name The Name to give to the Device.
Must be a NULL-terminated ASL NameString
e.g.: "DEV0", "DV15.DEV0", etc.
@param [in] Uid UID for the CMN600 device.
@param [in] Uid UID for the CMN device.
@param [out] Table If success, pointer to the created SSDT table.
@retval EFI_SUCCESS Table generated successfully.
@ -224,19 +292,21 @@ error_handler:
STATIC
EFI_STATUS
EFIAPI
FixupCmn600Info (
IN CONST CM_ARM_CMN_600_INFO *Cmn600Info,
FixupCmnInfo (
IN CONST CM_ARM_CMN_INFO *CmnInfo,
IN CONST CHAR8 *Name,
IN CONST UINT64 Uid,
OUT EFI_ACPI_DESCRIPTION_HEADER **Table
)
{
AML_OBJECT_NODE_HANDLE NameOpHidNode;
EFI_STATUS Status;
EFI_STATUS Status1;
UINT8 Index;
CONST CHAR8 *Hid;
CONST CM_ARCH_COMMON_GENERIC_INTERRUPT *DtcInt;
EFI_ACPI_DESCRIPTION_HEADER *SsdtCmn600Template;
EFI_ACPI_DESCRIPTION_HEADER *SsdtCmnTemplate;
AML_ROOT_NODE_HANDLE RootNodeHandle;
AML_OBJECT_NODE_HANDLE NameOpIdNode;
AML_OBJECT_NODE_HANDLE NameOpCrsNode;
@ -244,25 +314,45 @@ FixupCmn600Info (
AML_DATA_NODE_HANDLE CmnRootNodeBaseRdNode;
AML_OBJECT_NODE_HANDLE DeviceNode;
// Parse the Ssdt CMN-600 Template.
SsdtCmn600Template = (EFI_ACPI_DESCRIPTION_HEADER *)
ssdtcmn600template_aml_code;
Hid = GetCmnHid (CmnInfo->CmnType);
if (Hid == NULL) {
return EFI_INVALID_PARAMETER;
}
// Parse the Ssdt CMN Template.
SsdtCmnTemplate = (EFI_ACPI_DESCRIPTION_HEADER *)
ssdtcmntemplate_aml_code;
RootNodeHandle = NULL;
Status = AmlParseDefinitionBlock (
SsdtCmn600Template,
SsdtCmnTemplate,
&RootNodeHandle
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"ERROR: SSDT-CMN-600: Failed to parse SSDT CMN-600 Template."
"ERROR: SSDT-CMN: Failed to parse SSDT CMN Template."
" Status = %r\n",
Status
));
return Status;
}
Status = AmlFindNode (
RootNodeHandle,
"\\_SB_.CMN0._HID",
&NameOpHidNode
);
if (EFI_ERROR (Status)) {
goto error_handler;
}
Status = AmlNameOpUpdateString (NameOpHidNode, Hid);
if (EFI_ERROR (Status)) {
goto error_handler;
}
// Get the _UID NameOp object defined by the "Name ()" statement,
// and update its value.
Status = AmlFindNode (
@ -292,11 +382,17 @@ FixupCmn600Info (
// Get the first Rd node in the "_CRS" object.
// This is the PERIPHBASE node.
Status = AmlNameOpGetFirstRdNode (NameOpCrsNode, &CmnPeriphBaseRdNode);
if (EFI_ERROR (Status)) {
if (EFI_ERROR (Status) || (CmnPeriphBaseRdNode == NULL)) {
Status = EFI_INVALID_PARAMETER;
goto error_handler;
}
if (CmnPeriphBaseRdNode == NULL) {
// Get the second resource descriptor: the optional ROOT region.
Status = AmlNameOpGetNextRdNode (
CmnPeriphBaseRdNode,
&CmnRootNodeBaseRdNode
);
if (EFI_ERROR (Status) || (CmnRootNodeBaseRdNode == NULL)) {
Status = EFI_INVALID_PARAMETER;
goto error_handler;
}
@ -304,45 +400,42 @@ FixupCmn600Info (
// Update the PERIPHBASE base address and length.
Status = AmlUpdateRdQWord (
CmnPeriphBaseRdNode,
Cmn600Info->PeriphBaseAddress,
Cmn600Info->PeriphBaseAddressLength
CmnInfo->PeriphBaseAddress,
CmnInfo->PeriphBaseAddressLength
);
if (EFI_ERROR (Status)) {
goto error_handler;
}
// Get the QWord node corresponding to the ROOTNODEBASE.
// It is the second Resource Data element in the BufferNode's
// variable list of arguments.
Status = AmlNameOpGetNextRdNode (
CmnPeriphBaseRdNode,
&CmnRootNodeBaseRdNode
);
if (EFI_ERROR (Status)) {
goto error_handler;
}
if (HasCmnRootNode (CmnInfo)) {
Status = AmlUpdateRdQWord (
CmnRootNodeBaseRdNode,
CmnInfo->RootNodeBaseAddress,
CmnInfo->RootNodeBaseAddressLength
);
if (EFI_ERROR (Status)) {
goto error_handler;
}
} else {
Status = AmlDetachNode (CmnRootNodeBaseRdNode);
if (EFI_ERROR (Status)) {
goto error_handler;
}
if (CmnRootNodeBaseRdNode == NULL) {
Status = EFI_INVALID_PARAMETER;
goto error_handler;
}
Status = AmlDeleteTree (CmnRootNodeBaseRdNode);
if (EFI_ERROR (Status)) {
goto error_handler;
}
// Update the ROOTNODEBASE base address and length.
Status = AmlUpdateRdQWord (
CmnRootNodeBaseRdNode,
Cmn600Info->RootNodeBaseAddress,
ROOTNODEBASE_ADDRESS_LENGTH
);
if (EFI_ERROR (Status)) {
goto error_handler;
CmnRootNodeBaseRdNode = NULL;
}
// Add the Interrupt node(s).
// Generate Resource Data node(s) corresponding to the "Interrupt ()"
// ASL function and add it at the last position in the list of
// Resource Data nodes.
for (Index = 0; Index < Cmn600Info->DtcCount; Index++) {
DtcInt = &Cmn600Info->DtcInterrupt[Index];
for (Index = 0; Index < CmnInfo->DtcCount; Index++) {
DtcInt = &CmnInfo->DtcInterrupt[Index];
Status = AmlCodeGenRdInterrupt (
((DtcInt->Flags &
@ -363,7 +456,7 @@ FixupCmn600Info (
}
} // for
// Fixup the CMN600 device name.
// Fixup the CMN device name.
// This MUST be done at the end, otherwise AML paths won't be valid anymore.
// Get the CMN0 variable defined by the "Device ()" statement.
Status = AmlFindNode (RootNodeHandle, "\\_SB_.CMN0", &DeviceNode);
@ -371,7 +464,7 @@ FixupCmn600Info (
goto error_handler;
}
// Update the CMN600 Device's name.
// Update the CMN Device's name.
Status = AmlDeviceOpUpdateName (DeviceNode, Name);
if (EFI_ERROR (Status)) {
goto error_handler;
@ -385,7 +478,7 @@ FixupCmn600Info (
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"ERROR: SSDT-CMN-600: Failed to Serialize SSDT Table Data."
"ERROR: SSDT-CMN: Failed to Serialize SSDT Table Data."
" Status = %r\n",
Status
));
@ -398,7 +491,7 @@ error_handler:
if (EFI_ERROR (Status1)) {
DEBUG ((
DEBUG_ERROR,
"ERROR: SSDT-CMN-600: Failed to cleanup AML tree."
"ERROR: SSDT-CMN: Failed to cleanup AML tree."
" Status = %r\n",
Status1
));
@ -413,7 +506,7 @@ error_handler:
return Status;
}
/** Free any resources allocated for constructing the SSDT tables for CMN-600.
/** Free any resources allocated for constructing the SSDT tables for CMN.
@param [in] This Pointer to the ACPI table generator.
@param [in] AcpiTableInfo Pointer to the ACPI Table Info.
@ -429,7 +522,7 @@ error_handler:
STATIC
EFI_STATUS
EFIAPI
FreeSsdtCmn600TableResourcesEx (
FreeSsdtCmnTableResourcesEx (
IN CONST ACPI_TABLE_GENERATOR *CONST This,
IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
@ -450,7 +543,7 @@ FreeSsdtCmn600TableResourcesEx (
(*Table == NULL) ||
(TableCount == 0))
{
DEBUG ((DEBUG_ERROR, "ERROR: SSDT-CMN-600: Invalid Table Pointer\n"));
DEBUG ((DEBUG_ERROR, "ERROR: SSDT-CMN: Invalid Table Pointer\n"));
return EFI_INVALID_PARAMETER;
}
@ -465,7 +558,7 @@ FreeSsdtCmn600TableResourcesEx (
} else {
DEBUG ((
DEBUG_ERROR,
"ERROR: SSDT-CMN-600: Could not free SSDT table at index %d."
"ERROR: SSDT-CMN: Could not free SSDT table at index %d."
" Status = %r\n",
Index,
EFI_INVALID_PARAMETER
@ -480,7 +573,7 @@ FreeSsdtCmn600TableResourcesEx (
return EFI_SUCCESS;
}
/** Construct SSDT tables for describing CMN-600 meshes.
/** Construct SSDT tables for describing CMN meshes.
This function invokes the Configuration Manager protocol interface
to get the required hardware information for generating the ACPI
@ -508,7 +601,7 @@ FreeSsdtCmn600TableResourcesEx (
STATIC
EFI_STATUS
EFIAPI
BuildSsdtCmn600TableEx (
BuildSsdtCmnTableEx (
IN CONST ACPI_TABLE_GENERATOR *This,
IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
@ -518,8 +611,8 @@ BuildSsdtCmn600TableEx (
{
EFI_STATUS Status;
UINT64 Index;
CM_ARM_CMN_600_INFO *Cmn600Info;
UINT32 Cmn600Count;
CM_ARM_CMN_INFO *CmnInfo;
UINT32 CmnCount;
CHAR8 NewName[AML_NAME_SEG_SIZE + 1];
EFI_ACPI_DESCRIPTION_HEADER **TableList;
@ -533,39 +626,39 @@ BuildSsdtCmn600TableEx (
*Table = NULL;
// Get CMN-600 information.
Status = GetEArmObjCmn600Info (
// Get CMN information.
Status = GetEArmObjCmnInfo (
CfgMgrProtocol,
CM_NULL_TOKEN,
&Cmn600Info,
&Cmn600Count
&CmnInfo,
&CmnCount
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"ERROR: SSDT-CMN-600: Failed to get the CMN-600 information."
"ERROR: SSDT-CMN: Failed to get the CMN information."
" Status = %r\n",
Status
));
return Status;
}
if ((Cmn600Count == 0) || (Cmn600Count > MAX_CMN600_DEVICES_SUPPORTED)) {
if ((CmnCount == 0) || (CmnCount > MAX_CMN_DEVICES_SUPPORTED)) {
DEBUG ((
DEBUG_ERROR,
"ERROR: SSDT-CMN-600: CMN600 peripheral count = %d."
"ERROR: SSDT-CMN: CMN device count = %d."
" This must be between 1 to 16.\n",
Cmn600Count
CmnCount
));
return EFI_INVALID_PARAMETER;
}
// Validate the CMN-600 Info.
Status = ValidateCmn600Info (Cmn600Info, Cmn600Count);
// Validate the CMN Info.
Status = ValidateCmnInfo (CmnInfo, CmnCount);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"ERROR: SSDT-CMN-600: Invalid CMN600 information. Status = %r\n",
"ERROR: SSDT-CMN: Invalid CMN information. Status = %r\n",
Status
));
return Status;
@ -574,13 +667,13 @@ BuildSsdtCmn600TableEx (
// Allocate a table to store pointers to the SSDT tables.
TableList = (EFI_ACPI_DESCRIPTION_HEADER **)
AllocateZeroPool (
(sizeof (EFI_ACPI_DESCRIPTION_HEADER *) * Cmn600Count)
(sizeof (EFI_ACPI_DESCRIPTION_HEADER *) * CmnCount)
);
if (TableList == NULL) {
Status = EFI_OUT_OF_RESOURCES;
DEBUG ((
DEBUG_ERROR,
"ERROR: SSDT-CMN-600: Failed to allocate memory for Table List."
"ERROR: SSDT-CMN: Failed to allocate memory for Table List."
" Status = %r\n",
Status
));
@ -595,12 +688,12 @@ BuildSsdtCmn600TableEx (
NewName[1] = 'M';
NewName[2] = 'N';
NewName[4] = '\0';
for (Index = 0; Index < Cmn600Count; Index++) {
for (Index = 0; Index < CmnCount; Index++) {
NewName[3] = AsciiFromHex ((UINT8)(Index));
// Build a SSDT table describing the CMN600 device.
Status = FixupCmn600Info (
&Cmn600Info[Index],
// Build a SSDT table describing the CMN device.
Status = FixupCmnInfo (
&CmnInfo[Index],
NewName,
Index,
&TableList[Index]
@ -608,7 +701,7 @@ BuildSsdtCmn600TableEx (
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"ERROR: SSDT-CMN-600: Failed to build associated SSDT table."
"ERROR: SSDT-CMN: Failed to build associated SSDT table."
" Status = %r\n",
Status
));
@ -620,25 +713,25 @@ BuildSsdtCmn600TableEx (
*TableCount += 1;
} // for
// Note: Table list and CMN600 device count has been setup. The
// framework will invoke FreeSsdtCmn600TableResourcesEx() even
// Note: Table list and CMN device count has been setup. The
// framework will invoke FreeSsdtCmnTableResourcesEx() even
// on failure, so appropriate clean-up will be done.
return Status;
}
/** This macro defines the Raw Generator revision.
*/
#define SSDT_CMN_600_GENERATOR_REVISION CREATE_REVISION (1, 0)
#define SSDT_CMN_GENERATOR_REVISION CREATE_REVISION (1, 0)
/** The interface for the Raw Table Generator.
*/
STATIC
CONST
ACPI_TABLE_GENERATOR SsdtCmn600Generator = {
ACPI_TABLE_GENERATOR SsdtCmnGenerator = {
// Generator ID
CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtCmn600),
CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtCmn),
// Generator Description
L"ACPI.STD.SSDT.CMN600.GENERATOR",
L"ACPI.STD.SSDT.CMN.GENERATOR",
// ACPI Table Signature
EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
// ACPI Table Revision - Unused
@ -648,15 +741,15 @@ ACPI_TABLE_GENERATOR SsdtCmn600Generator = {
// Creator ID
TABLE_GENERATOR_CREATOR_ID_ARM,
// Creator Revision
SSDT_CMN_600_GENERATOR_REVISION,
SSDT_CMN_GENERATOR_REVISION,
// Build table function. Use the extended version instead.
NULL,
// Free table function. Use the extended version instead.
NULL,
// Build Table function
BuildSsdtCmn600TableEx,
BuildSsdtCmnTableEx,
// Free Resource function
FreeSsdtCmn600TableResourcesEx
FreeSsdtCmnTableResourcesEx
};
/** Register the Generator with the ACPI Table Factory.
@ -671,17 +764,17 @@ ACPI_TABLE_GENERATOR SsdtCmn600Generator = {
**/
EFI_STATUS
EFIAPI
AcpiSsdtCmn600LibConstructor (
AcpiSsdtCmnLibConstructor (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
Status = RegisterAcpiTableGenerator (&SsdtCmn600Generator);
Status = RegisterAcpiTableGenerator (&SsdtCmnGenerator);
DEBUG ((
DEBUG_INFO,
"SSDT-CMN-600: Register Generator. Status = %r\n",
"SSDT-CMN: Register Generator. Status = %r\n",
Status
));
ASSERT_EFI_ERROR (Status);
@ -699,17 +792,17 @@ AcpiSsdtCmn600LibConstructor (
**/
EFI_STATUS
EFIAPI
AcpiSsdtCmn600LibDestructor (
AcpiSsdtCmnLibDestructor (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
Status = DeregisterAcpiTableGenerator (&SsdtCmn600Generator);
Status = DeregisterAcpiTableGenerator (&SsdtCmnGenerator);
DEBUG ((
DEBUG_INFO,
"SSDT-CMN-600: Deregister Generator. Status = %r\n",
"SSDT-CMN: Deregister Generator. Status = %r\n",
Status
));
ASSERT_EFI_ERROR (Status);

View file

@ -0,0 +1,49 @@
/** @file
Copyright (c) 2020 - 2026, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Glossary:
- Cm or CM - Configuration Manager
- Obj or OBJ - Object
- Std or STD - Standard
@par Reference(s):
- Arm CoreLink CMN-600 Coherent Mesh Network Technical Reference Manual r3p0
- Generic ACPI for Arm Components 1.3 Platform Design Document
**/
#pragma once
/** CMN ACPI Hardware IDs. */
#define ACPI_HID_CMN_600 "ARMHC600"
#define ACPI_HID_CMN_650 "ARMHC650"
#define ACPI_HID_CMN_700 "ARMHC700"
#define ACPI_HID_CMN_S3 "ARMHC003"
/** PeriphBase maximum address length is 256MB (0x10000000)
for a (X >= 4) || (Y >= 4) dimensions mesh.
*/
#define CMN600_PERIPHBASE_MAX_ADDRESS_LENGTH SIZE_256MB
/** Required alignment of the CMN configuration region base address.
*/
#define CMN_PERIPHBASE_ADDRESS_ALIGNMENT SIZE_64MB
/** RootNodeBase address length is 16KB (0x00004000).
*/
#define CMN600_ROOTNODEBASE_ADDRESS_LENGTH SIZE_16KB
/** Maximum number of CMN Debug and Trace Logic Controllers (DTC).
*/
#define MAX_CMN_DTC_COUNT 4
/** Maximum CMN devices supported by this generator.
This generator supports a maximum of 16 CMN devices.
Note: This is not a hard limitation and can be extended if needed.
Corresponding changes would be needed to support the Name and
UID fields describing the CMN device.
*/
#define MAX_CMN_DEVICES_SUPPORTED 16

View file

@ -1,25 +1,25 @@
## @file
# Ssdt CMN-600 Table Generator
# Ssdt CMN Table Generator
#
# Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
# Copyright (c) 2021 - 2026, Arm Limited. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
[Defines]
INF_VERSION = 0x0001001B
BASE_NAME = SsdtCmn600LibArm
BASE_NAME = SsdtCmnLibArm
FILE_GUID = CEDB450D-8F0E-4ACC-8FB7-F72EC7D216A4
VERSION_STRING = 1.0
MODULE_TYPE = DXE_DRIVER
LIBRARY_CLASS = NULL|DXE_DRIVER
CONSTRUCTOR = AcpiSsdtCmn600LibConstructor
DESTRUCTOR = AcpiSsdtCmn600LibDestructor
CONSTRUCTOR = AcpiSsdtCmnLibConstructor
DESTRUCTOR = AcpiSsdtCmnLibDestructor
[Sources]
SsdtCmn600Generator.c
SsdtCmn600Generator.h
SsdtCmn600Template.asl
SsdtCmnGenerator.c
SsdtCmnGenerator.h
SsdtCmnTemplate.asl
[Packages]
MdePkg/MdePkg.dec

View file

@ -1,28 +1,28 @@
/** @file
SSDT CMN-600 Template
SSDT CMN Template
Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
Copyright (c) 2020 - 2026, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Reference(s):
- Arm CoreLink CMN-600 Coherent Mesh Network Technical Reference Manual r3p0
- Generic ACPI for Arm Components 1.0 Platform Design Document
- Generic ACPI for Arm Components 1.3 Platform Design Document
@par Glossary:
- {template} - Data fixed up using AML Fixup APIs.
- {codegen} - Data generated using AML Codegen APIs.
**/
DefinitionBlock ("SsdtCmn600.aml", "SSDT", 2, "ARMLTD", "CMN-600", 1) {
DefinitionBlock ("SsdtCmn.aml", "SSDT", 2, "ARMLTD", "CMN", 1) {
Scope (_SB) {
// CMN-600 device object for a X * Y mesh, where (X >= 4) || (Y >= 4).
// CMN device object.
Device (CMN0) { // {template}
Name (_HID, "ARMHC600")
Name (_HID, "ARMHC600") // {template}
Name (_UID, 0x0) // {template}
Name (_CRS, ResourceTemplate () {
// Descriptor for 256 MB of the CFG region at offset PERIPHBASE.
// Descriptor for the CMN configuration region.
QWordMemory (
ResourceConsumer, // bit 0 of general flags is 0.
PosDecode,

View file

@ -1,7 +1,7 @@
/** @file
Configuration Manager object token fixer
Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
Copyright (c) 2021 - 2026, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@ -235,7 +235,7 @@ CM_OBJECT_TOKEN_FIXER ArmTokenFixer[EArmObjMax] = {
NULL, ///< 17 - GIC ITS Identifier Array
NULL, ///< 18 - ID Mapping Array
NULL, ///< 19 - SMMU Interrupt Array
NULL, ///< 20 - CMN-600 Info
NULL, ///< 20 - CMN Info
NULL, ///< 21 - Reserved Memory Range Node
NULL, ///< 22 - Memory Range Descriptor
NULL ///< 23 - Embedded Trace Extension/Module Info

View file

@ -434,25 +434,27 @@ STATIC CONST CM_OBJ_PARSER CmArmDmc620PmuRegInfoParser[] = {
ARRAY_SIZE (CmArchCommonGenericInterruptParser) },
};
/** A parser for EArmObjCmn600Info.
/** A parser for EArmObjCmnInfo containing CMN information.
*/
STATIC CONST CM_OBJ_PARSER CmArmCmn600InfoParser[] = {
{ "PeriphBaseAddress", 8, "0x%llx", NULL },
{ "PeriphBaseAddressLength", 8, "0x%llx", NULL },
{ "RootNodeBaseAddress", 8, "0x%llx", NULL },
{ "DtcCount", 1, "0x%x", NULL },
{ "DtcIntr[0]", sizeof (CM_ARCH_COMMON_GENERIC_INTERRUPT),
STATIC CONST CM_OBJ_PARSER CmArmCmnInfoParser[] = {
{ "PeriphBaseAddress", 8, "0x%llx", NULL },
{ "PeriphBaseAddressLength", 8, "0x%llx", NULL },
{ "RootNodeBaseAddress", 8, "0x%llx", NULL },
{ "DtcCount", 1, "0x%x", NULL },
{ "DtcIntr[0]", sizeof (CM_ARCH_COMMON_GENERIC_INTERRUPT),
NULL, NULL, CmArchCommonGenericInterruptParser,
ARRAY_SIZE (CmArchCommonGenericInterruptParser) },
{ "DtcIntr[1]", sizeof (CM_ARCH_COMMON_GENERIC_INTERRUPT),
{ "DtcIntr[1]", sizeof (CM_ARCH_COMMON_GENERIC_INTERRUPT),
NULL, NULL, CmArchCommonGenericInterruptParser,
ARRAY_SIZE (CmArchCommonGenericInterruptParser) },
{ "DtcIntr[2]", sizeof (CM_ARCH_COMMON_GENERIC_INTERRUPT),
{ "DtcIntr[2]", sizeof (CM_ARCH_COMMON_GENERIC_INTERRUPT),
NULL, NULL, CmArchCommonGenericInterruptParser,
ARRAY_SIZE (CmArchCommonGenericInterruptParser) },
{ "DtcIntr[3]", sizeof (CM_ARCH_COMMON_GENERIC_INTERRUPT),
{ "DtcIntr[3]", sizeof (CM_ARCH_COMMON_GENERIC_INTERRUPT),
NULL, NULL, CmArchCommonGenericInterruptParser,
ARRAY_SIZE (CmArchCommonGenericInterruptParser) },
{ "CmnType", sizeof (ARM_CMN_TYPE), "0x%x", NULL },
{ "RootNodeBaseAddressLength", 8, "0x%llx", NULL },
};
/** A parser for the EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE structure.
@ -1526,7 +1528,7 @@ STATIC CONST CM_OBJ_PARSER_ARRAY ArmNamespaceObjectParser[] = {
CM_PARSER_ADD_OBJECT (EArmObjGicItsIdentifierArray, CmArmGicItsIdentifierParser),
CM_PARSER_ADD_OBJECT (EArmObjIdMappingArray, CmArmIdMappingParser),
CM_PARSER_ADD_OBJECT (EArmObjSmmuInterruptArray, CmArchCommonGenericInterruptParser),
CM_PARSER_ADD_OBJECT (EArmObjCmn600Info, CmArmCmn600InfoParser),
CM_PARSER_ADD_OBJECT (EArmObjCmnInfo, CmArmCmnInfoParser),
CM_PARSER_ADD_OBJECT (EArmObjRmr, CmArmRmrInfoParser),
CM_PARSER_ADD_OBJECT (EArmObjMemoryRangeDescriptor, CmArmMemoryRangeDescriptorInfoParser),
CM_PARSER_ADD_OBJECT (EArmObjEtInfo, CmArmEtInfo),

View file

@ -485,7 +485,7 @@ The CM_OBJECT_ID type is used to identify the Configuration Manager
| 17 | GIC ITS Identifier Array | |
| 18 | ID Mapping Array | |
| 19 | SMMU Interrupt Array | |
| 20 | CMN 600 Info | |
| 20 | CMN Info | |
| 21 | Reserved Memory Range Node | |
| 22 | Memory Range Descriptor | |
| 23 | Embedded Trace Extension/Module Info | |