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]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to