diff options
author | Sami Mujawar <sami.mujawar@arm.com> | 2022-07-14 17:50:31 +0100 |
---|---|---|
committer | mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> | 2022-07-29 19:22:15 +0000 |
commit | e9150618ec91f79e70a1719ac8c198bee34a99be (patch) | |
tree | ccc9d3986259b57f389c91f32a8dff053ac535c7 | |
parent | de200b7e2c3c5bdb7b6eb8c3cc947ae6f053eb38 (diff) | |
download | edk2-e9150618ec91f79e70a1719ac8c198bee34a99be.tar.gz edk2-e9150618ec91f79e70a1719ac8c198bee34a99be.tar.bz2 edk2-e9150618ec91f79e70a1719ac8c198bee34a99be.zip |
DynamicTablesPkg: IORT generator updates for Rev E.d spec
Bugzilla: 3458 - Add support IORT Rev E.d specification updates
(https://bugzilla.tianocore.org/show_bug.cgi?id=3458)
The IO Remapping Table, Platform Design Document, Revision E.d,
Feb 2022 (https://developer.arm.com/documentation/den0049/)
introduces the following updates, collectively including the
updates and errata fixes to Rev E, Rev E.a, Rev E.b, Rev E.c:
- increments the IORT table revision to 5.
- updates the node definition to add an 'Identifier' field.
- adds definition of node type 6 - Reserved Memory Range node.
- adds definition for Memory Range Descriptors.
- adds flag to indicate PRI support for root complexes.
- adds flag to indicate if the root complex supports forwarding
of PASID information on translated transactions to the SMMU.
- adds flag to indicate if the root complex supports PASID.
- adds flags to define access privilege and attributes for the
memory ranges.
Therefore, update the IORT generator to:
- increment IORT table revision count to 5.
- populate Identifier filed if revision is greater than 4.
- add support to populate Reserved Memory Range nodes and
the Memory range descriptors.
- add validation to check that the Identifier field is
unique.
- Populate the PASID capabilities and Flags field of the
Root complex node.
- Added checks to not generate IORT Rev E, Rev E.<a,b,c>.
Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
Reviewed-by: Pierre Gondois <pierre.gondois@arm.com>
-rw-r--r-- | DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.c | 655 | ||||
-rw-r--r-- | DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.h | 5 |
2 files changed, 610 insertions, 50 deletions
diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.c index 63381441e2..40d99162cc 100644 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.c +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.c @@ -5,8 +5,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
@par Reference(s):
- - IO Remapping Table, Platform Design Document,
- Document number: ARM DEN 0049D, Issue D, March 2018
+ - IO Remapping Table, Platform Design Document, Revision E.d, Feb 2022
+ (https://developer.arm.com/documentation/den0049/)
**/
@@ -37,9 +37,11 @@ Requirements: - EArmObjSmmuV1SmmuV2
- EArmObjSmmuV3
- EArmObjPmcg
+ - EArmObjRmr
- EArmObjGicItsIdentifierArray
- EArmObjIdMappingArray
- - EArmObjGicItsIdentifierArray
+ - EArmObjSmmuInterruptArray
+ - EArmObjMemoryRangeDescriptor
*/
/** This macro expands to a function that retrieves the ITS
@@ -97,6 +99,24 @@ GET_OBJECT_LIST ( );
/** This macro expands to a function that retrieves the
+ RMR node information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+ EObjNameSpaceArm,
+ EArmObjRmr,
+ CM_ARM_RMR_NODE
+ );
+
+/** This macro expands to a function that retrieves the
+ Memory Range Descriptor Array information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+ EObjNameSpaceArm,
+ EArmObjMemoryRangeDescriptor,
+ CM_ARM_MEMORY_RANGE_DESCRIPTOR
+ );
+
+/** This macro expands to a function that retrieves the
ITS Identifier Array information from the Configuration Manager.
*/
GET_OBJECT_LIST (
@@ -174,16 +194,19 @@ GetSizeofItsGroupNodes ( Size = 0;
while (NodeCount-- != 0) {
- (*NodeIndexer)->Token = NodeList->Token;
- (*NodeIndexer)->Object = (VOID *)NodeList;
- (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);
+ (*NodeIndexer)->Token = NodeList->Token;
+ (*NodeIndexer)->Object = (VOID *)NodeList;
+ (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);
+ (*NodeIndexer)->Identifier = NodeList->Identifier;
DEBUG ((
DEBUG_INFO,
- "IORT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n",
+ "IORT: Node Indexer = %p, Token = %p, Object = %p,"
+ " Offset = 0x%x, Identifier = 0x%x\n",
*NodeIndexer,
(*NodeIndexer)->Token,
(*NodeIndexer)->Object,
- (*NodeIndexer)->Offset
+ (*NodeIndexer)->Offset,
+ (*NodeIndexer)->Identifier
));
Size += GetItsGroupNodeSize (NodeList);
@@ -248,16 +271,19 @@ GetSizeofNamedComponentNodes ( Size = 0;
while (NodeCount-- != 0) {
- (*NodeIndexer)->Token = NodeList->Token;
- (*NodeIndexer)->Object = (VOID *)NodeList;
- (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);
+ (*NodeIndexer)->Token = NodeList->Token;
+ (*NodeIndexer)->Object = (VOID *)NodeList;
+ (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);
+ (*NodeIndexer)->Identifier = NodeList->Identifier;
DEBUG ((
DEBUG_INFO,
- "IORT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n",
+ "IORT: Node Indexer = %p, Token = %p, Object = %p,"
+ " Offset = 0x%x, Identifier = 0x%x\n",
*NodeIndexer,
(*NodeIndexer)->Token,
(*NodeIndexer)->Object,
- (*NodeIndexer)->Offset
+ (*NodeIndexer)->Offset,
+ (*NodeIndexer)->Identifier
));
Size += GetNamedComponentNodeSize (NodeList);
@@ -320,16 +346,19 @@ GetSizeofRootComplexNodes ( Size = 0;
while (NodeCount-- != 0) {
- (*NodeIndexer)->Token = NodeList->Token;
- (*NodeIndexer)->Object = (VOID *)NodeList;
- (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);
+ (*NodeIndexer)->Token = NodeList->Token;
+ (*NodeIndexer)->Object = (VOID *)NodeList;
+ (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);
+ (*NodeIndexer)->Identifier = NodeList->Identifier;
DEBUG ((
DEBUG_INFO,
- "IORT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n",
+ "IORT: Node Indexer = %p, Token = %p, Object = %p,"
+ " Offset = 0x%x, Identifier = 0x%x\n",
*NodeIndexer,
(*NodeIndexer)->Token,
(*NodeIndexer)->Object,
- (*NodeIndexer)->Offset
+ (*NodeIndexer)->Offset,
+ (*NodeIndexer)->Identifier
));
Size += GetRootComplexNodeSize (NodeList);
@@ -398,16 +427,19 @@ GetSizeofSmmuV1V2Nodes ( Size = 0;
while (NodeCount-- != 0) {
- (*NodeIndexer)->Token = NodeList->Token;
- (*NodeIndexer)->Object = (VOID *)NodeList;
- (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);
+ (*NodeIndexer)->Token = NodeList->Token;
+ (*NodeIndexer)->Object = (VOID *)NodeList;
+ (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);
+ (*NodeIndexer)->Identifier = NodeList->Identifier;
DEBUG ((
DEBUG_INFO,
- "IORT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n",
+ "IORT: Node Indexer = %p, Token = %p, Object = %p,"
+ " Offset = 0x%x, Identifier = 0x%x\n",
*NodeIndexer,
(*NodeIndexer)->Token,
(*NodeIndexer)->Object,
- (*NodeIndexer)->Offset
+ (*NodeIndexer)->Offset,
+ (*NodeIndexer)->Identifier
));
Size += GetSmmuV1V2NodeSize (NodeList);
@@ -470,16 +502,19 @@ GetSizeofSmmuV3Nodes ( Size = 0;
while (NodeCount-- != 0) {
- (*NodeIndexer)->Token = NodeList->Token;
- (*NodeIndexer)->Object = (VOID *)NodeList;
- (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);
+ (*NodeIndexer)->Token = NodeList->Token;
+ (*NodeIndexer)->Object = (VOID *)NodeList;
+ (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);
+ (*NodeIndexer)->Identifier = NodeList->Identifier;
DEBUG ((
DEBUG_INFO,
- "IORT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n",
+ "IORT: Node Indexer = %p, Token = %p, Object = %p,"
+ " Offset = 0x%x, Identifier = 0x%x\n",
*NodeIndexer,
(*NodeIndexer)->Token,
(*NodeIndexer)->Object,
- (*NodeIndexer)->Offset
+ (*NodeIndexer)->Offset,
+ (*NodeIndexer)->Identifier
));
Size += GetSmmuV3NodeSize (NodeList);
@@ -542,16 +577,19 @@ GetSizeofPmcgNodes ( Size = 0;
while (NodeCount-- != 0) {
- (*NodeIndexer)->Token = NodeList->Token;
- (*NodeIndexer)->Object = (VOID *)NodeList;
- (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);
+ (*NodeIndexer)->Token = NodeList->Token;
+ (*NodeIndexer)->Object = (VOID *)NodeList;
+ (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);
+ (*NodeIndexer)->Identifier = NodeList->Identifier;
DEBUG ((
DEBUG_INFO,
- "IORT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n",
+ "IORT: Node Indexer = %p, Token = %p, Object = %p,"
+ " Offset = 0x%x, Identifier = 0x%x\n",
*NodeIndexer,
(*NodeIndexer)->Token,
(*NodeIndexer)->Object,
- (*NodeIndexer)->Offset
+ (*NodeIndexer)->Offset,
+ (*NodeIndexer)->Identifier
));
Size += GetPmcgNodeSize (NodeList);
@@ -562,6 +600,84 @@ GetSizeofPmcgNodes ( return Size;
}
+/** Returns the size of the RMR node.
+
+ @param [in] Node Pointer to RMR node.
+
+ @retval Size of the RMR node.
+**/
+STATIC
+UINT32
+GetRmrNodeSize (
+ IN CONST CM_ARM_RMR_NODE *Node
+ )
+{
+ ASSERT (Node != NULL);
+
+ /* Size of RMR node +
+ Size of ID mapping array +
+ Size of Memory Range Descriptor array
+ */
+ return (UINT32)(sizeof (EFI_ACPI_6_0_IO_REMAPPING_RMR_NODE) +
+ (Node->IdMappingCount *
+ sizeof (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE)) +
+ (Node->MemRangeDescCount *
+ sizeof (EFI_ACPI_6_0_IO_REMAPPING_MEM_RANGE_DESC)));
+}
+
+/** Returns the total size required for the RMR nodes and
+ updates the Node Indexer.
+
+ This function calculates the size required for the node group
+ and also populates the Node Indexer array with offsets for the
+ individual nodes.
+
+ @param [in] NodeStartOffset Offset from the start of the
+ IORT where this node group starts.
+ @param [in] NodeList Pointer to RMR node list.
+ @param [in] NodeCount Count of the RMR nodes.
+ @param [in, out] NodeIndexer Pointer to the next Node Indexer.
+
+ @retval Total size of the RMR nodes.
+**/
+STATIC
+UINT64
+GetSizeofRmrNodes (
+ IN CONST UINT32 NodeStartOffset,
+ IN CONST CM_ARM_RMR_NODE *NodeList,
+ IN UINT32 NodeCount,
+ IN OUT IORT_NODE_INDEXER **CONST NodeIndexer
+ )
+{
+ UINT64 Size;
+
+ ASSERT (NodeList != NULL);
+
+ Size = 0;
+ while (NodeCount-- != 0) {
+ (*NodeIndexer)->Token = NodeList->Token;
+ (*NodeIndexer)->Object = (VOID *)NodeList;
+ (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset);
+ (*NodeIndexer)->Identifier = NodeList->Identifier;
+ DEBUG ((
+ DEBUG_INFO,
+ "IORT: Node Indexer = %p, Token = %p, Object = %p,"
+ " Offset = 0x%x, Identifier = 0x%x\n",
+ *NodeIndexer,
+ (*NodeIndexer)->Token,
+ (*NodeIndexer)->Object,
+ (*NodeIndexer)->Offset,
+ (*NodeIndexer)->Identifier
+ ));
+
+ Size += GetRmrNodeSize (NodeList);
+ (*NodeIndexer)++;
+ NodeList++;
+ }
+
+ return Size;
+}
+
/** Returns the offset of the Node referenced by the Token.
@param [in] NodeIndexer Pointer to node indexer array.
@@ -713,6 +829,7 @@ AddIdMappingArray ( @param [in] This Pointer to the table Generator.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol Interface.
+ @param [in] AcpiTableInfo Pointer to the ACPI table info structure.
@param [in] Iort Pointer to IORT table structure.
@param [in] NodesStartOffset Offset for the start of the ITS Group
Nodes.
@@ -729,6 +846,7 @@ EFI_STATUS AddItsGroupNodes (
IN CONST ACPI_TABLE_GENERATOR *CONST This,
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,
IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE *Iort,
IN CONST UINT32 NodesStartOffset,
IN CONST CM_ARM_ITS_GROUP_NODE *NodeList,
@@ -765,11 +883,19 @@ AddItsGroupNodes ( // Populate the node header
ItsGroupNode->Node.Type = EFI_ACPI_IORT_TYPE_ITS_GROUP;
ItsGroupNode->Node.Length = (UINT16)NodeLength;
- ItsGroupNode->Node.Revision = 0;
- ItsGroupNode->Node.Identifier = EFI_ACPI_RESERVED_DWORD;
ItsGroupNode->Node.NumIdMappings = 0;
ItsGroupNode->Node.IdReference = 0;
+ if (AcpiTableInfo->AcpiTableRevision <
+ EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05)
+ {
+ ItsGroupNode->Node.Revision = 0;
+ ItsGroupNode->Node.Identifier = EFI_ACPI_RESERVED_DWORD;
+ } else {
+ ItsGroupNode->Node.Revision = 1;
+ ItsGroupNode->Node.Identifier = NodeList->Identifier;
+ }
+
// IORT specific data
ItsGroupNode->NumItsIdentifiers = NodeList->ItsIdCount;
ItsIds = (UINT32 *)((UINT8 *)ItsGroupNode +
@@ -820,6 +946,7 @@ AddItsGroupNodes ( @param [in] This Pointer to the table Generator.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol Interface.
+ @param [in] AcpiTableInfo Pointer to the ACPI table info structure.
@param [in] Iort Pointer to IORT table structure.
@param [in] NodesStartOffset Offset for the start of the Named
Component Nodes.
@@ -836,6 +963,7 @@ EFI_STATUS AddNamedComponentNodes (
IN CONST ACPI_TABLE_GENERATOR *CONST This,
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,
IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE *Iort,
IN CONST UINT32 NodesStartOffset,
IN CONST CM_ARM_NAMED_COMPONENT_NODE *NodeList,
@@ -871,10 +999,18 @@ AddNamedComponentNodes ( // Populate the node header
NcNode->Node.Type = EFI_ACPI_IORT_TYPE_NAMED_COMP;
NcNode->Node.Length = (UINT16)NodeLength;
- NcNode->Node.Revision = 2;
- NcNode->Node.Identifier = EFI_ACPI_RESERVED_DWORD;
NcNode->Node.NumIdMappings = NodeList->IdMappingCount;
+ if (AcpiTableInfo->AcpiTableRevision <
+ EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05)
+ {
+ NcNode->Node.Revision = 2;
+ NcNode->Node.Identifier = EFI_ACPI_RESERVED_DWORD;
+ } else {
+ NcNode->Node.Revision = 4;
+ NcNode->Node.Identifier = NodeList->Identifier;
+ }
+
ObjectNameLength = AsciiStrLen (NodeList->ObjectName) + 1;
NcNode->Node.IdReference = (NodeList->IdMappingCount == 0) ?
0 : ((UINT32)(sizeof (EFI_ACPI_6_0_IO_REMAPPING_NAMED_COMP_NODE) +
@@ -955,6 +1091,7 @@ AddNamedComponentNodes ( @param [in] This Pointer to the table Generator.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol Interface.
+ @param [in] AcpiTableInfo Pointer to the ACPI table info structure.
@param [in] Iort Pointer to IORT table structure.
@param [in] NodesStartOffset Offset for the start of the Root Complex
Nodes.
@@ -971,6 +1108,7 @@ EFI_STATUS AddRootComplexNodes (
IN CONST ACPI_TABLE_GENERATOR *CONST This,
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,
IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE *Iort,
IN CONST UINT32 NodesStartOffset,
IN CONST CM_ARM_ROOT_COMPLEX_NODE *NodeList,
@@ -1004,12 +1142,23 @@ AddRootComplexNodes ( // Populate the node header
RcNode->Node.Type = EFI_ACPI_IORT_TYPE_ROOT_COMPLEX;
RcNode->Node.Length = (UINT16)NodeLength;
- RcNode->Node.Revision = 1;
- RcNode->Node.Identifier = EFI_ACPI_RESERVED_DWORD;
RcNode->Node.NumIdMappings = NodeList->IdMappingCount;
RcNode->Node.IdReference = (NodeList->IdMappingCount == 0) ?
0 : sizeof (EFI_ACPI_6_0_IO_REMAPPING_RC_NODE);
+ if (AcpiTableInfo->AcpiTableRevision <
+ EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05)
+ {
+ RcNode->Node.Revision = 1;
+ RcNode->Node.Identifier = EFI_ACPI_RESERVED_DWORD;
+ RcNode->PasidCapabilities = EFI_ACPI_RESERVED_WORD;
+ } else {
+ RcNode->Node.Revision = 4;
+ RcNode->Node.Identifier = NodeList->Identifier;
+ RcNode->PasidCapabilities = NodeList->PasidCapabilities;
+ RcNode->Flags = NodeList->Flags;
+ }
+
// Root Complex specific data
RcNode->CacheCoherent = NodeList->CacheCoherent;
RcNode->AllocationHints = NodeList->AllocationHints;
@@ -1018,7 +1167,6 @@ AddRootComplexNodes ( RcNode->AtsAttribute = NodeList->AtsAttribute;
RcNode->PciSegmentNumber = NodeList->PciSegmentNumber;
RcNode->MemoryAddressSize = NodeList->MemoryAddressSize;
- RcNode->PasidCapabilities = EFI_ACPI_RESERVED_WORD;
RcNode->Reserved1[0] = EFI_ACPI_RESERVED_BYTE;
if (NodeList->IdMappingCount > 0) {
@@ -1134,6 +1282,7 @@ AddSmmuInterruptArray ( @param [in] This Pointer to the table Generator.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol Interface.
+ @param [in] AcpiTableInfo Pointer to the ACPI table info structure.
@param [in] Iort Pointer to IORT table structure.
@param [in] NodesStartOffset Offset for the start of the SMMU v1/v2
Nodes.
@@ -1150,6 +1299,7 @@ EFI_STATUS AddSmmuV1V2Nodes (
IN CONST ACPI_TABLE_GENERATOR *CONST This,
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,
IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE *Iort,
IN CONST UINT32 NodesStartOffset,
IN CONST CM_ARM_SMMUV1_SMMUV2_NODE *NodeList,
@@ -1186,8 +1336,6 @@ AddSmmuV1V2Nodes ( // Populate the node header
SmmuNode->Node.Type = EFI_ACPI_IORT_TYPE_SMMUv1v2;
SmmuNode->Node.Length = (UINT16)NodeLength;
- SmmuNode->Node.Revision = 0;
- SmmuNode->Node.Identifier = EFI_ACPI_RESERVED_DWORD;
SmmuNode->Node.NumIdMappings = NodeList->IdMappingCount;
SmmuNode->Node.IdReference = (NodeList->IdMappingCount == 0) ?
0 : (sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE) +
@@ -1196,6 +1344,16 @@ AddSmmuV1V2Nodes ( (NodeList->PmuInterruptCount *
sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT)));
+ if (AcpiTableInfo->AcpiTableRevision <
+ EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05)
+ {
+ SmmuNode->Node.Revision = 1;
+ SmmuNode->Node.Identifier = EFI_ACPI_RESERVED_DWORD;
+ } else {
+ SmmuNode->Node.Revision = 3;
+ SmmuNode->Node.Identifier = NodeList->Identifier;
+ }
+
// SMMU v1/v2 specific data
SmmuNode->Base = NodeList->BaseAddress;
SmmuNode->Span = NodeList->Span;
@@ -1339,6 +1497,7 @@ AddSmmuV1V2Nodes ( @param [in] This Pointer to the table Generator.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol Interface.
+ @param [in] AcpiTableInfo Pointer to the ACPI table info structure.
@param [in] Iort Pointer to IORT table structure.
@param [in] NodesStartOffset Offset for the start of the SMMUv3 Nodes.
@param [in] NodeList Pointer to an array of SMMUv3 Node Objects.
@@ -1353,6 +1512,7 @@ EFI_STATUS AddSmmuV3Nodes (
IN CONST ACPI_TABLE_GENERATOR *CONST This,
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,
IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE *Iort,
IN CONST UINT32 NodesStartOffset,
IN CONST CM_ARM_SMMUV3_NODE *NodeList,
@@ -1385,12 +1545,20 @@ AddSmmuV3Nodes ( // Populate the node header
SmmuV3Node->Node.Type = EFI_ACPI_IORT_TYPE_SMMUv3;
SmmuV3Node->Node.Length = (UINT16)NodeLength;
- SmmuV3Node->Node.Revision = 2;
- SmmuV3Node->Node.Identifier = EFI_ACPI_RESERVED_DWORD;
SmmuV3Node->Node.NumIdMappings = NodeList->IdMappingCount;
SmmuV3Node->Node.IdReference = (NodeList->IdMappingCount == 0) ?
0 : sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU3_NODE);
+ if (AcpiTableInfo->AcpiTableRevision <
+ EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05)
+ {
+ SmmuV3Node->Node.Revision = 2;
+ SmmuV3Node->Node.Identifier = EFI_ACPI_RESERVED_DWORD;
+ } else {
+ SmmuV3Node->Node.Revision = 4;
+ SmmuV3Node->Node.Identifier = NodeList->Identifier;
+ }
+
// SMMUv3 specific data
SmmuV3Node->Base = NodeList->BaseAddress;
SmmuV3Node->Flags = NodeList->Flags;
@@ -1468,6 +1636,7 @@ AddSmmuV3Nodes ( @param [in] This Pointer to the table Generator.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol Interface.
+ @param [in] AcpiTableInfo Pointer to the ACPI table info structure.
@param [in] Iort Pointer to IORT table structure.
@param [in] NodesStartOffset Offset for the start of the PMCG Nodes.
@param [in] NodeList Pointer to an array of PMCG Node Objects.
@@ -1482,6 +1651,7 @@ EFI_STATUS AddPmcgNodes (
IN CONST ACPI_TABLE_GENERATOR *CONST This,
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,
IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE *Iort,
IN CONST UINT32 NodesStartOffset,
IN CONST CM_ARM_PMCG_NODE *NodeList,
@@ -1516,12 +1686,20 @@ AddPmcgNodes ( // Populate the node header
PmcgNode->Node.Type = EFI_ACPI_IORT_TYPE_PMCG;
PmcgNode->Node.Length = (UINT16)NodeLength;
- PmcgNode->Node.Revision = 1;
- PmcgNode->Node.Identifier = EFI_ACPI_RESERVED_DWORD;
PmcgNode->Node.NumIdMappings = NodeList->IdMappingCount;
PmcgNode->Node.IdReference = (NodeList->IdMappingCount == 0) ?
0 : sizeof (EFI_ACPI_6_0_IO_REMAPPING_PMCG_NODE);
+ if (AcpiTableInfo->AcpiTableRevision <
+ EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05)
+ {
+ PmcgNode->Node.Revision = 1;
+ PmcgNode->Node.Identifier = EFI_ACPI_RESERVED_DWORD;
+ } else {
+ PmcgNode->Node.Revision = 2;
+ PmcgNode->Node.Identifier = NodeList->Identifier;
+ }
+
// PMCG specific data
PmcgNode->Base = NodeList->BaseAddress;
PmcgNode->OverflowInterruptGsiv = NodeList->OverflowInterrupt;
@@ -1588,6 +1766,274 @@ AddPmcgNodes ( return EFI_SUCCESS;
}
+/** Update the Memory Range Descriptor Array.
+
+ This function retrieves the Memory Range Descriptor objects referenced by
+ MemRangeDescToken and updates the Memory Range Descriptor array.
+
+ @param [in] This Pointer to the table Generator.
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager
+ Protocol Interface.
+ @param [in] DescArray Pointer to an array of Memory Range
+ Descriptors.
+ @param [in] DescCount Number of Id Descriptors.
+ @param [in] DescToken Reference Token for retrieving the
+ Memory Range Descriptor Array.
+
+ @retval EFI_SUCCESS Table generated successfully.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_NOT_FOUND The required object was not found.
+**/
+STATIC
+EFI_STATUS
+AddMemRangeDescArray (
+ IN CONST ACPI_TABLE_GENERATOR *CONST This,
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
+ IN EFI_ACPI_6_0_IO_REMAPPING_MEM_RANGE_DESC *DescArray,
+ IN UINT32 DescCount,
+ IN CONST CM_OBJECT_TOKEN DescToken
+ )
+{
+ EFI_STATUS Status;
+ CM_ARM_MEMORY_RANGE_DESCRIPTOR *MemRangeDesc;
+ UINT32 MemRangeDescCount;
+
+ ASSERT (DescArray != NULL);
+
+ // Get the Id Mapping Array
+ Status = GetEArmObjMemoryRangeDescriptor (
+ CfgMgrProtocol,
+ DescToken,
+ &MemRangeDesc,
+ &MemRangeDescCount
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: IORT: Failed to get Memory Range Descriptor array. Status = %r\n",
+ Status
+ ));
+ return Status;
+ }
+
+ if (MemRangeDescCount < DescCount) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: IORT: Failed to get the required number of Memory"
+ " Range Descriptors.\n"
+ ));
+ return EFI_NOT_FOUND;
+ }
+
+ // Populate the Memory Range Descriptor array
+ while (DescCount-- != 0) {
+ DescArray->Base = MemRangeDesc->BaseAddress;
+ DescArray->Length = MemRangeDesc->Length;
+ DescArray->Reserved = EFI_ACPI_RESERVED_DWORD;
+
+ DescArray++;
+ MemRangeDesc++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/** Update the RMR Node Information.
+
+ This function updates the RMR node information in the IORT table.
+
+ @param [in] This Pointer to the table Generator.
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager
+ Protocol Interface.
+ @param [in] AcpiTableInfo Pointer to the ACPI table info structure.
+ @param [in] Iort Pointer to IORT table structure.
+ @param [in] NodesStartOffset Offset for the start of the PMCG Nodes.
+ @param [in] NodeList Pointer to an array of PMCG Node Objects.
+ @param [in] NodeCount Number of PMCG Node Objects.
+
+ @retval EFI_SUCCESS Table generated successfully.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_NOT_FOUND The required object was not found.
+**/
+STATIC
+EFI_STATUS
+AddRmrNodes (
+ IN CONST ACPI_TABLE_GENERATOR *CONST This,
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,
+ IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE *Iort,
+ IN CONST UINT32 NodesStartOffset,
+ IN CONST CM_ARM_RMR_NODE *NodeList,
+ IN UINT32 NodeCount
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_6_0_IO_REMAPPING_RMR_NODE *RmrNode;
+ EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE *IdMapArray;
+ EFI_ACPI_6_0_IO_REMAPPING_MEM_RANGE_DESC *MemRangeDescArray;
+ UINT64 NodeLength;
+
+ ASSERT (Iort != NULL);
+
+ RmrNode = (EFI_ACPI_6_0_IO_REMAPPING_RMR_NODE *)((UINT8 *)Iort +
+ NodesStartOffset);
+
+ while (NodeCount-- != 0) {
+ NodeLength = GetRmrNodeSize (NodeList);
+ if (NodeLength > MAX_UINT16) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: IORT: RMR Node length 0x%lx > MAX_UINT16. Status = %r\n",
+ NodeLength,
+ Status
+ ));
+ return Status;
+ }
+
+ if (NodeList->MemRangeDescCount == 0) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: IORT: Memory Range Desc count = %d. Status = %r\n",
+ NodeList->MemRangeDescCount,
+ Status
+ ));
+ return Status;
+ }
+
+ if (NodeList->MemRangeDescToken == CM_NULL_TOKEN) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: IORT: Invalid Memory Range Descriptor token,"
+ " Token = 0x%x. Status = %r\n",
+ NodeList->MemRangeDescToken,
+ Status
+ ));
+ return Status;
+ }
+
+ // Populate the node header
+ RmrNode->Node.Type = EFI_ACPI_IORT_TYPE_RMR;
+ RmrNode->Node.Length = (UINT16)NodeLength;
+ RmrNode->Node.Revision = 3;
+ RmrNode->Node.Identifier = NodeList->Identifier;
+ RmrNode->Node.NumIdMappings = NodeList->IdMappingCount;
+ RmrNode->Node.IdReference = (NodeList->IdMappingCount == 0) ?
+ 0 : sizeof (EFI_ACPI_6_0_IO_REMAPPING_RMR_NODE);
+
+ // RMR specific data
+ RmrNode->Flags = NodeList->Flags;
+ RmrNode->NumMemRangeDesc = NodeList->MemRangeDescCount;
+ RmrNode->MemRangeDescRef = (NodeList->MemRangeDescCount == 0) ?
+ 0 : (sizeof (EFI_ACPI_6_0_IO_REMAPPING_RMR_NODE) +
+ (NodeList->IdMappingCount *
+ sizeof (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE)));
+
+ if (NodeList->IdMappingCount > 0) {
+ if (NodeList->IdMappingToken == CM_NULL_TOKEN) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: IORT: Invalid Id Mapping token,"
+ " Token = 0x%x, Status =%r\n",
+ NodeList->IdMappingToken,
+ Status
+ ));
+ return Status;
+ }
+
+ // Ids for RMR node
+ IdMapArray = (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE *)((UINT8 *)RmrNode +
+ RmrNode->Node.IdReference);
+
+ Status = AddIdMappingArray (
+ This,
+ CfgMgrProtocol,
+ IdMapArray,
+ NodeList->IdMappingCount,
+ NodeList->IdMappingToken
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: IORT: Failed to add Id Mapping Array. Status = %r\n",
+ Status
+ ));
+ return Status;
+ }
+ }
+
+ // Memory Range Descriptors for RMR node
+ MemRangeDescArray = (EFI_ACPI_6_0_IO_REMAPPING_MEM_RANGE_DESC *)(
+ (UINT8 *)RmrNode +
+ RmrNode->MemRangeDescRef
+ );
+
+ Status = AddMemRangeDescArray (
+ This,
+ CfgMgrProtocol,
+ MemRangeDescArray,
+ NodeList->MemRangeDescCount,
+ NodeList->MemRangeDescToken
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: IORT: Failed to Memory Range Descriptor Array. Status = %r\n",
+ Status
+ ));
+ return Status;
+ }
+
+ // Next RMR Node
+ RmrNode = (EFI_ACPI_6_0_IO_REMAPPING_RMR_NODE *)((UINT8 *)RmrNode +
+ RmrNode->Node.Length);
+ NodeList++;
+ } // RMR Node
+
+ return EFI_SUCCESS;
+}
+
+/** Validates that the IORT nodes Identifier are unique.
+
+ @param [in] NodeIndexer Pointer to the Node Indexer.
+ @param [in] NodeCount Number of IORT Nodes.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Identifier field not unique.
+**/
+STATIC
+EFI_STATUS
+ValidateNodeIdentifiers (
+ IN CONST IORT_NODE_INDEXER *CONST NodeIndexer,
+ IN UINT32 NodeCount
+ )
+{
+ UINT32 IndexI;
+ UINT32 IndexJ;
+
+ for (IndexI = 0; IndexI < NodeCount; IndexI++) {
+ for (IndexJ = 0; IndexJ < NodeCount; IndexJ++) {
+ if ((IndexI != IndexJ) &&
+ (NodeIndexer[IndexI].Identifier == NodeIndexer[IndexJ].Identifier))
+ {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: IORT: UID %d of Token %p matches with that of Token %p.\n",
+ NodeIndexer[IndexI].Identifier,
+ NodeIndexer[IndexI].Token,
+ NodeIndexer[IndexJ].Token
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+ }// IndexJ
+ } // IndexI
+
+ return EFI_SUCCESS;
+}
+
/** Construct the IORT ACPI table.
This function invokes the Configuration Manager protocol interface
@@ -1632,6 +2078,7 @@ BuildIortTable ( UINT32 SmmuV1V2NodeCount;
UINT32 SmmuV3NodeCount;
UINT32 PmcgNodeCount;
+ UINT32 RmrNodeCount;
UINT32 ItsGroupOffset;
UINT32 NamedComponentOffset;
@@ -1639,6 +2086,7 @@ BuildIortTable ( UINT32 SmmuV1V2Offset;
UINT32 SmmuV3Offset;
UINT32 PmcgOffset;
+ UINT32 RmrOffset;
CM_ARM_ITS_GROUP_NODE *ItsGroupNodeList;
CM_ARM_NAMED_COMPONENT_NODE *NamedComponentNodeList;
@@ -1646,6 +2094,7 @@ BuildIortTable ( CM_ARM_SMMUV1_SMMUV2_NODE *SmmuV1V2NodeList;
CM_ARM_SMMUV3_NODE *SmmuV3NodeList;
CM_ARM_PMCG_NODE *PmcgNodeList;
+ CM_ARM_RMR_NODE *RmrNodeList;
EFI_ACPI_6_0_IO_REMAPPING_TABLE *Iort;
IORT_NODE_INDEXER *NodeIndexer;
@@ -1672,6 +2121,16 @@ BuildIortTable ( return EFI_INVALID_PARAMETER;
}
+ if ((AcpiTableInfo->AcpiTableRevision > EFI_ACPI_IO_REMAPPING_TABLE_REVISION_00) &&
+ (AcpiTableInfo->AcpiTableRevision < EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05))
+ {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: IORT: Revisions E (1), E.a(2),b(3),c(4) are not supported.\n"
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+
Generator = (ACPI_IORT_GENERATOR *)This;
*Table = NULL;
@@ -1789,6 +2248,29 @@ BuildIortTable ( // Add the PMCG node count
IortNodeCount += PmcgNodeCount;
+ if (AcpiTableInfo->AcpiTableRevision >=
+ EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05)
+ {
+ // Get the RMR node info
+ Status = GetEArmObjRmr (
+ CfgMgrProtocol,
+ CM_NULL_TOKEN,
+ &RmrNodeList,
+ &RmrNodeCount
+ );
+ if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: IORT: Failed to get RMR Node Info. Status = %r\n",
+ Status
+ ));
+ goto error_handler;
+ }
+
+ // Add the RMR node count
+ IortNodeCount += RmrNodeCount;
+ }
+
// Allocate Node Indexer array
NodeIndexer = (IORT_NODE_INDEXER *)AllocateZeroPool (
(sizeof (IORT_NODE_INDEXER) *
@@ -1998,6 +2480,40 @@ BuildIortTable ( ));
}
+ // RMR Nodes
+ if ((AcpiTableInfo->AcpiTableRevision >=
+ EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05) &&
+ (RmrNodeCount > 0))
+ {
+ RmrOffset = (UINT32)TableSize;
+ // Size of RMR node list.
+ NodeSize = GetSizeofRmrNodes (
+ RmrOffset,
+ RmrNodeList,
+ RmrNodeCount,
+ &NodeIndexer
+ );
+ if (NodeSize > MAX_UINT32) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: IORT: Invalid Size of RMR Nodes. Status = %r\n",
+ Status
+ ));
+ goto error_handler;
+ }
+
+ TableSize += NodeSize;
+
+ DEBUG ((
+ DEBUG_INFO,
+ " RmrNodeCount = %d\n" \
+ " RmrOffset = %d\n",
+ RmrNodeCount,
+ RmrOffset
+ ));
+ }
+
DEBUG ((
DEBUG_INFO,
"INFO: IORT:\n" \
@@ -2019,6 +2535,21 @@ BuildIortTable ( goto error_handler;
}
+ // Validate that the identifiers for the nodes are unique
+ if (AcpiTableInfo->AcpiTableRevision >=
+ EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05)
+ {
+ Status = ValidateNodeIdentifiers (Generator->NodeIndexer, IortNodeCount);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: IORT: Node Identifier not unique. Status = %r\n",
+ Status
+ ));
+ goto error_handler;
+ }
+ }
+
// Allocate the Buffer for IORT table
*Table = (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (TableSize);
if (*Table == NULL) {
@@ -2067,6 +2598,7 @@ BuildIortTable ( Status = AddItsGroupNodes (
This,
CfgMgrProtocol,
+ AcpiTableInfo,
Iort,
ItsGroupOffset,
ItsGroupNodeList,
@@ -2086,6 +2618,7 @@ BuildIortTable ( Status = AddNamedComponentNodes (
This,
CfgMgrProtocol,
+ AcpiTableInfo,
Iort,
NamedComponentOffset,
NamedComponentNodeList,
@@ -2105,6 +2638,7 @@ BuildIortTable ( Status = AddRootComplexNodes (
This,
CfgMgrProtocol,
+ AcpiTableInfo,
Iort,
RootComplexOffset,
RootComplexNodeList,
@@ -2124,6 +2658,7 @@ BuildIortTable ( Status = AddSmmuV1V2Nodes (
This,
CfgMgrProtocol,
+ AcpiTableInfo,
Iort,
SmmuV1V2Offset,
SmmuV1V2NodeList,
@@ -2143,6 +2678,7 @@ BuildIortTable ( Status = AddSmmuV3Nodes (
This,
CfgMgrProtocol,
+ AcpiTableInfo,
Iort,
SmmuV3Offset,
SmmuV3NodeList,
@@ -2162,6 +2698,7 @@ BuildIortTable ( Status = AddPmcgNodes (
This,
CfgMgrProtocol,
+ AcpiTableInfo,
Iort,
PmcgOffset,
PmcgNodeList,
@@ -2170,7 +2707,27 @@ BuildIortTable ( if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
- "ERROR: IORT: Failed to add SMMUv3 Node. Status = %r\n",
+ "ERROR: IORT: Failed to add PMCG Node. Status = %r\n",
+ Status
+ ));
+ goto error_handler;
+ }
+ }
+
+ if (RmrNodeCount > 0) {
+ Status = AddRmrNodes (
+ This,
+ CfgMgrProtocol,
+ AcpiTableInfo,
+ Iort,
+ RmrOffset,
+ RmrNodeList,
+ RmrNodeCount
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: IORT: Failed to add RMR Node. Status = %r\n",
Status
));
goto error_handler;
@@ -2255,9 +2812,9 @@ ACPI_IORT_GENERATOR IortGenerator = { // Generator Description
L"ACPI.STD.IORT.GENERATOR",
// ACPI Table Signature
- EFI_ACPI_6_2_IO_REMAPPING_TABLE_SIGNATURE,
+ EFI_ACPI_6_4_IO_REMAPPING_TABLE_SIGNATURE,
// ACPI Table Revision supported by this Generator
- EFI_ACPI_IO_REMAPPING_TABLE_REVISION_00,
+ EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05,
// Minimum supported ACPI Table Revision
EFI_ACPI_IO_REMAPPING_TABLE_REVISION_00,
// Creator ID
diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.h b/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.h index 61f6b6153f..99d86b3d16 100644 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.h +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.h @@ -1,6 +1,6 @@ /** @file
- Copyright (c) 2018, ARM Limited. All rights reserved.
+ Copyright (c) 2018 - 2022, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -25,6 +25,9 @@ typedef struct IortNodeIndexer { VOID *Object;
/// Node offset from the start of the IORT table
UINT32 Offset;
+
+ /// Unique identifier for the Node
+ UINT32 Identifier;
} IORT_NODE_INDEXER;
typedef struct AcpiIortGenerator {
|