Hi Pierre,
Thank you for the feedback.
Please find my response inline marked [SAMI].
Regards,
Sami Mujawar
On 13/07/2022 01:18 pm, Pierre Gondois wrote:
Hi Sami,
@@ -37,9 +37,11 @@ Requirements:
- EArmObjSmmuV1SmmuV2
- EArmObjSmmuV3
- EArmObjPmcg
+ - EArmObjRmr
- EArmObjGicItsIdentifierArray
- EArmObjIdMappingArray
- - EArmObjGicItsIdentifierArray
I think EArmObjGicItsIdentifierArray should be conserved.
[SAMI] This is present. I have removed the duplicate entry.
+ - EArmObjSmmuInterruptArray
+ - EArmObjMemoryRangeDescriptor
*/
/** This macro expands to a function that retrieves the ITS
@@ -96,6 +98,24 @@ GET_OBJECT_LIST (
CM_ARM_PMCG_NODE
);
+/** 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.
*/
@@ -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
I think all the GetSizeof...Nodes() functions should be merged as one
and take a callback as an argument. This would help factorizing.
For instance for GetSizeofItsGroupNodes():
typedef UINT32 (*GET_NODE_SIZE_CB) (
IN CONST VOID *Node
);
STATIC
UINT64
GetSizeofNodes (
IN UINT32 NodeType,
IN CONST UINT32 NodeStartOffset,
IN CONST CM_ARM_ITS_GROUP_NODE *NodeList,
IN UINT32 NodeCount,
IN GET_NODE_SIZE *GetNodeSizeCb,
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 += GetNodeSizeCb (NodeList);
(*NodeIndexer)++;
NodeList++;
}
return Size;
}
And then:
GetSizeofItsGroupNodes (...)
becomes:
GetSizeofNodes (..., GetItsGroupNodeSize, ...)
(ideally done in a separate patch)
[SAMI] Agree. However, this is a different patch and not part of this
series.
));
[snip]
+/** 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) {
I think this should be '!='
[SAMI] This is not really required as we are using DescCount to add the
nodes. So even if the ConfigurationManager returns more than the
required number of nodes, we only use the first DescCount nodes. The
remaining are ignored.
+ 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;
+}
+
[snip]
+
/** 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;
@@ -1789,6 +2238,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 +2470,40 @@ BuildIortTable (
));
}
+ // RMR Nodes
+ if ((AcpiTableInfo->AcpiTableRevision >=
+ EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05) &&
+ (RmrNodeCount > 0))
+ {
There are a few checks like this on the revision.
It seems that the 'Identifier' field was added in rev E (=1)
and its size was increased in E.a (=2). So the identifier
field should theoretically be generated for a Revision >= 1.
As we jump from rev D (=0) t5 E.d (=5), maybe we generation
of IORT tables with a revision in between should be prevented.
[SAMI] Ack. I will add a check to say generation of IORT table for
revisions 1 to 4 is not supported.
Regards,
Pierre
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#91320): https://edk2.groups.io/g/devel/message/91320
Mute This Topic: https://groups.io/mt/92334083/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-