[edk2-devel] [PATCH v1 03/14] DynamicTablesPkg: FdtHwInfoParser: Add FDT utility functions

PierreGondois posted 14 patches 4 years, 7 months ago
There is a newer version of this series
[edk2-devel] [PATCH v1 03/14] DynamicTablesPkg: FdtHwInfoParser: Add FDT utility functions
Posted by PierreGondois 4 years, 7 months ago
From: Pierre Gondois <Pierre.Gondois@arm.com>

The FdtHwInfoParser parses a platform Device Tree and populates
the Platform Information repository with Configuration Manager
objects.

Therefore, add a set of helper functions to simplify parsing of
the platform Device Tree.

Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 .../Library/FdtHwInfoParserLib/FdtUtility.c   | 909 ++++++++++++++++++
 .../Library/FdtHwInfoParserLib/FdtUtility.h   | 458 +++++++++
 2 files changed, 1367 insertions(+)
 create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.c
 create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.h

diff --git a/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.c b/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.c
new file mode 100644
index 000000000000..0fca82aedf9e
--- /dev/null
+++ b/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.c
@@ -0,0 +1,909 @@
+/** @file
+  Flattened device tree utility.
+
+  Copyright (c) 2021, ARM Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Reference(s):
+  - Device tree Specification - Release v0.3
+  - linux/Documentation/devicetree/bindings/interrupt-controller/arm%2Cgic.yaml
+  - linux//Documentation/devicetree/bindings/interrupt-controller/arm%2Cgic.yaml
+**/
+
+#include <FdtHwInfoParserInclude.h>
+#include "FdtUtility.h"
+
+/** Get the interrupt Id of an interrupt described in a fdt.
+
+  Data must describe a GIC interrupt. A GIC interrupt is on at least
+  3 UINT32 cells.
+  This function DOES NOT SUPPORT extended SPI range and extended PPI range.
+
+  @param [in]  Data   Pointer to the first cell of an "interrupts" property.
+
+  @retval  The interrupt id.
+**/
+UINT32
+EFIAPI
+FdtGetInterruptId (
+  UINT32 CONST  * Data
+  )
+{
+  UINT32  IrqType;
+  UINT32  IrqId;
+
+  ASSERT (Data != NULL);
+
+  IrqType = fdt32_to_cpu (Data[IRQ_TYPE_OFFSET]);
+  IrqId = fdt32_to_cpu (Data[IRQ_NUMBER_OFFSET]);
+
+  switch (IrqType) {
+  case DT_SPI_IRQ:
+    IrqId += SPI_OFFSET;
+    break;
+
+  case DT_PPI_IRQ:
+    IrqId += PPI_OFFSET;
+    break;
+
+  default:
+    ASSERT (0);
+    IrqId = 0;
+  }
+
+  return IrqId;
+}
+
+/** Get the ACPI interrupt flags of an interrupt described in a fdt.
+
+  Data must describe a GIC interrupt. A GIC interrupt is on at least
+  3 UINT32 cells.
+
+  PPI interrupt cpu mask on bits [15:8] are ignored.
+
+  @param [in]  Data   Pointer to the first cell of an "interrupts" property.
+
+  @retval  The interrupt flags (for ACPI).
+**/
+UINT32
+EFIAPI
+FdtGetInterruptFlags (
+  UINT32 CONST  * Data
+  )
+{
+  UINT32  IrqFlags;
+  UINT32  AcpiIrqFlags;
+
+  ASSERT (Data != NULL);
+
+  IrqFlags = fdt32_to_cpu (Data[IRQ_FLAGS_OFFSET]);
+
+  AcpiIrqFlags = DT_IRQ_IS_EDGE_TRIGGERED (IrqFlags) ? BIT0 : 0;
+  AcpiIrqFlags |= DT_IRQ_IS_ACTIVE_LOW (IrqFlags) ? BIT1 : 0;
+
+  return AcpiIrqFlags;
+}
+
+/** Check whether a node has the input name.
+
+  @param [in]  Fdt          Pointer to a Flattened Device Tree.
+  @param [in]  Node         Offset of the node to check the name.
+  @param [in]  SearchName   Node name to search.
+                            This is a NULL terminated string.
+
+  @retval True    The node has the input name.
+  @retval FALSE   Otherwise, or error.
+**/
+STATIC
+BOOLEAN
+EFIAPI
+FdtNodeHasName (
+  IN  CONST VOID  * Fdt,
+  IN        INT32   Node,
+  IN  CONST VOID  * SearchName
+  )
+{
+  CONST CHAR8   * NodeName;
+  UINT32          Length;
+
+  if ((Fdt == NULL) ||
+      (SearchName == NULL)) {
+    ASSERT (0);
+    return FALSE;
+  }
+
+  // Always compare the whole string. Don't stop at the "@" char.
+  Length = (UINT32)AsciiStrLen (SearchName);
+
+  // Get the address of the node name.
+  NodeName = fdt_offset_ptr (Fdt, Node + FDT_TAGSIZE, Length + 1);
+  if (NodeName == NULL) {
+    return FALSE;
+  }
+
+  // SearchName must be longer than the node name.
+  if (Length > AsciiStrLen (NodeName)) {
+    return FALSE;
+  }
+
+  // Use CompareMem here instead of AsciiStrnCmp as the NodeName
+  // may contain the node name followed by '@'0x<addr>.
+  if (AsciiStrnCmp (NodeName, SearchName, Length) != 0) {
+    return FALSE;
+  }
+
+  // The name matches perfectly, or
+  // the node name is XXX@addr and the XXX matches.
+  if ((NodeName[Length] == '\0') ||
+      (NodeName[Length] == '@')) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/** Iterate through the list of strings in the Context,
+    and check whether at least one string is matching the
+    "compatible" property of the node.
+
+  @param [in]  Fdt          Pointer to a Flattened Device Tree.
+  @param [in]  Node         Offset of the node to operate the check on.
+  @param [in]  CompatInfo   COMPATIBILITY_INFO containing the list of compatible
+                            strings to compare with the "compatible" property
+                            of the node.
+
+  @retval TRUE    At least one string matched, the node is compatible.
+  @retval FALSE   Otherwise, or error.
+**/
+BOOLEAN
+EFIAPI
+FdtNodeIsCompatible (
+  IN  CONST VOID                * Fdt,
+  IN        INT32                 Node,
+  IN  CONST VOID                * CompatInfo
+  )
+{
+  UINT32                      Index;
+  CONST COMPATIBILITY_STR   * CompatibleTable;
+  UINT32                      Count;
+  CONST VOID                * Prop;
+  INT32                       PropLen;
+
+  if ((Fdt == NULL) ||
+      (CompatInfo == NULL)) {
+    ASSERT (0);
+    return FALSE;
+  }
+
+  Count = ((COMPATIBILITY_INFO*)CompatInfo)->Count;
+  CompatibleTable = ((COMPATIBILITY_INFO*)CompatInfo)->CompatTable;
+
+  // Get the "compatible" property.
+  Prop = fdt_getprop (Fdt, Node, "compatible", &PropLen);
+  if ((Prop == NULL) || (PropLen < 0)) {
+    return FALSE;
+  }
+
+  for (Index = 0; Index < Count; Index++) {
+    if (fdt_stringlist_contains (
+           Prop,
+           PropLen,
+           CompatibleTable[Index].CompatStr
+           )) {
+      return TRUE;
+    }
+  } // for
+
+  return FALSE;
+}
+
+/** Check whether a node has a property.
+
+  @param [in]  Fdt          Pointer to a Flattened Device Tree.
+  @param [in]  Node         Offset of the node to operate the check on.
+  @param [in]  PropertyName Name of the property to search.
+                            This is a NULL terminated string.
+
+  @retval True    The node has the property.
+  @retval FALSE   Otherwise, or error.
+**/
+BOOLEAN
+EFIAPI
+FdtNodeHasProperty (
+  IN  CONST VOID  * Fdt,
+  IN        INT32   Node,
+  IN  CONST VOID  * PropertyName
+  )
+{
+  INT32         Size;
+  CONST VOID  * Prop;
+
+  if ((Fdt == NULL) ||
+      (PropertyName == NULL)) {
+    ASSERT (0);
+    return FALSE;
+  }
+
+  Prop = fdt_getprop (Fdt, Node, PropertyName, &Size);
+  if ((Prop == NULL) || (Size < 0)) {
+    return FALSE;
+  }
+  return TRUE;
+}
+
+/** Get the next node in the whole DT fulfilling a condition.
+
+  The condition to fulfill is checked by the NodeChecker function.
+  Context is passed to NodeChecker.
+
+  The Device tree is traversed in a depth-first search, starting from Node.
+  The input Node is skipped.
+
+  @param [in]  Fdt              Pointer to a Flattened Device Tree.
+  @param [in, out]  Node        At entry: Node offset to start the search.
+                                          This first node is skipped.
+                                          Write (-1) to search the whole tree.
+                                At exit:  If success, contains the offset of
+                                          the next node fulfilling the
+                                          condition.
+  @param [in, out]  Depth       Depth is incremented/decremented of the depth
+                                difference between the input Node and the
+                                output Node.
+                                E.g.: If the output Node is a child node
+                                of the input Node, contains (+1).
+  @param [in]  NodeChecker      Function called to check if the condition
+                                is fulfilled.
+  @param [in]  Context          Context for the NodeChecker.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_ABORTED             An error occurred.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_NOT_FOUND           No matching node found.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+FdtGetNextCondNode (
+  IN      CONST VOID              * Fdt,
+  IN OUT        INT32             * Node,
+  IN OUT        INT32             * Depth,
+  IN            NODE_CHECKER_FUNC   NodeChecker,
+  IN      CONST VOID              * Context
+  )
+{
+  INT32   CurrNode;
+
+  if ((Fdt == NULL)   ||
+      (Node == NULL)  ||
+      (Depth == NULL) ||
+      (NodeChecker == NULL)) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  CurrNode = *Node;
+  do {
+    CurrNode = fdt_next_node (Fdt, CurrNode, Depth);
+    if ((CurrNode == -FDT_ERR_NOTFOUND) ||
+        (*Depth < 0)) {
+      // End of the tree, no matching node found.
+      return EFI_NOT_FOUND;
+    } else if (CurrNode < 0) {
+      // An error occurred.
+      ASSERT (0);
+      return EFI_ABORTED;
+    }
+  }  while (!NodeChecker (Fdt, CurrNode, Context));
+
+  // Matching node found.
+  *Node = CurrNode;
+  return EFI_SUCCESS;
+}
+
+/** Get the next node in a branch fulfilling a condition.
+
+  The condition to fulfill is checked by the NodeChecker function.
+  Context is passed to NodeChecker.
+
+  The Device tree is traversed in a depth-first search, starting from Node.
+  The input Node is skipped.
+
+  @param [in]       Fdt             Pointer to a Flattened Device Tree.
+  @param [in]       FdtBranch       Only search in the sub-nodes of this
+                                    branch.
+                                    Write (-1) to search the whole tree.
+  @param [in]       NodeChecker     Function called to check if the condition
+                                    is fulfilled.
+  @param [in]       Context         Context for the NodeChecker.
+  @param [in, out]  Node            At entry: Node offset to start the search.
+                                         This first node is skipped.
+                                         Write (-1) to search the whole tree.
+                                    At exit:  If success, contains the offset
+                                         of the next node in the branch
+                                         fulfilling the condition.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_ABORTED             An error occurred.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_NOT_FOUND           No matching node found.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+FdtGetNextCondNodeInBranch (
+  IN      CONST VOID              * Fdt,
+  IN            INT32               FdtBranch,
+  IN            NODE_CHECKER_FUNC   NodeChecker,
+  IN      CONST VOID              * Context,
+  IN OUT        INT32             * Node
+  )
+{
+  EFI_STATUS    Status;
+  INT32         CurrNode;
+  INT32         Depth;
+
+  if ((Fdt == NULL)   ||
+      (Node == NULL)  ||
+      (NodeChecker == NULL)) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  CurrNode = FdtBranch;
+  Depth = 0;
+
+  // First, check the Node is in the sub-nodes of the branch.
+  // This allows to find the relative depth of Node in the branch.
+  if (CurrNode != *Node) {
+    for (CurrNode = fdt_next_node (Fdt, CurrNode, &Depth);
+         (CurrNode >= 0) && (Depth > 0);
+         CurrNode = fdt_next_node (Fdt, CurrNode, &Depth)) {
+      if (CurrNode == *Node) {
+        // Node found.
+        break;
+      }
+    } // for
+
+    if ((CurrNode < 0) || (Depth <= 0)) {
+      // Node is not a node in the branch, or an error occurred.
+      ASSERT (0);
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  // Get the next node in the tree fulfilling the condition,
+  // in any branch.
+  Status = FdtGetNextCondNode (
+             Fdt,
+             Node,
+             &Depth,
+             NodeChecker,
+             Context
+             );
+  if (EFI_ERROR (Status)) {
+    ASSERT (Status == EFI_NOT_FOUND);
+    return Status;
+  }
+
+  if (Depth <= 0) {
+    // The node found is not in the right branch.
+    return EFI_NOT_FOUND;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/** Get the next node in a branch having a matching name.
+
+  The Device tree is traversed in a depth-first search, starting from Node.
+  The input Node is skipped.
+
+  @param [in]       Fdt         Pointer to a Flattened Device Tree.
+  @param [in]       FdtBranch   Only search in the sub-nodes of this branch.
+                                Write (-1) to search the whole tree.
+  @param [in]       NodeName    The node name to search.
+                                This is a NULL terminated string.
+  @param [in, out]  Node        At entry: Node offset to start the search.
+                                          This first node is skipped.
+                                          Write (-1) to search the whole tree.
+                                At exit:  If success, contains the offset of
+                                          the next node in the branch
+                                          having a matching name.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_ABORTED             An error occurred.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_NOT_FOUND           No matching node found.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetNextNamedNodeInBranch (
+  IN      CONST VOID    * Fdt,
+  IN            INT32     FdtBranch,
+  IN      CONST CHAR8   * NodeName,
+  IN OUT        INT32   * Node
+  )
+{
+  return FdtGetNextCondNodeInBranch (
+           Fdt,
+           FdtBranch,
+           FdtNodeHasName,
+           NodeName,
+           Node
+           );
+}
+
+/** Get the next node in a branch with at least one compatible property.
+
+  The Device tree is traversed in a depth-first search, starting from Node.
+  The input Node is skipped.
+
+  @param [in]       Fdt         Pointer to a Flattened Device Tree.
+  @param [in]       FdtBranch   Only search in the sub-nodes of this branch.
+                                Write (-1) to search the whole tree.
+  @param [in]  CompatNamesInfo  Table of compatible strings to compare with
+                                the compatible property of the node.
+  @param [in, out]  Node        At entry: Node offset to start the search.
+                                          This first node is skipped.
+                                          Write (-1) to search the whole tree.
+                                At exit:  If success, contains the offset of
+                                          the next node in the branch
+                                          being compatible.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_ABORTED             An error occurred.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_NOT_FOUND           No matching node found.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetNextCompatNodeInBranch (
+  IN      CONST VOID                * Fdt,
+  IN            INT32                 FdtBranch,
+  IN      CONST COMPATIBILITY_INFO  * CompatNamesInfo,
+  IN OUT        INT32               * Node
+  )
+{
+  return FdtGetNextCondNodeInBranch (
+           Fdt,
+           FdtBranch,
+           FdtNodeIsCompatible,
+           (CONST VOID*)CompatNamesInfo,
+           Node
+           );
+}
+
+/** Get the next node in a branch having the PropName property.
+
+  The Device tree is traversed in a depth-first search, starting from Node.
+  The input Node is skipped.
+
+  @param [in]       Fdt         Pointer to a Flattened Device Tree.
+  @param [in]       FdtBranch   Only search in the sub-nodes of this branch.
+                                Write (-1) to search the whole tree.
+  @param [in]       PropName    Name of the property to search.
+                                This is a NULL terminated string.
+  @param [in, out]  Node        At entry: Node offset to start the search.
+                                          This first node is skipped.
+                                          Write (-1) to search the whole tree.
+                                At exit:  If success, contains the offset of
+                                          the next node in the branch
+                                          being compatible.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_ABORTED             An error occurred.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_NOT_FOUND           No matching node found.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetNextPropNodeInBranch (
+  IN      CONST VOID    * Fdt,
+  IN            INT32     FdtBranch,
+  IN      CONST CHAR8   * PropName,
+  IN OUT        INT32   * Node
+  )
+{
+  return FdtGetNextCondNodeInBranch (
+           Fdt,
+           FdtBranch,
+           FdtNodeHasProperty,
+           (CONST VOID*)PropName,
+           Node
+           );
+}
+
+/** Count the number of Device Tree nodes fulfilling a condition
+    in a Device Tree branch.
+
+  The condition to fulfill is checked by the NodeChecker function.
+  Context is passed to NodeChecker.
+
+  @param [in]  Fdt              Pointer to a Flattened Device Tree.
+  @param [in]  FdtBranch        Only search in the sub-nodes of this branch.
+                                Write (-1) to search the whole tree.
+  @param [in]  NodeChecker      Function called to check the condition is
+                                fulfilled.
+  @param [in]  Context          Context for the NodeChecker.
+  @param [out] NodeCount        If success, contains the count of nodes
+                                fulfilling the condition.
+                                Can be 0.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_ABORTED             An error occurred.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+FdtCountCondNodeInBranch (
+  IN  CONST VOID              * Fdt,
+  IN        INT32               FdtBranch,
+  IN        NODE_CHECKER_FUNC   NodeChecker,
+  IN  CONST VOID              * Context,
+  OUT       UINT32            * NodeCount
+  )
+{
+  EFI_STATUS    Status;
+  INT32         CurrNode;
+
+  if ((Fdt == NULL)         ||
+      (NodeChecker == NULL) ||
+      (NodeCount == NULL)) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *NodeCount = 0;
+  CurrNode = FdtBranch;
+  while (TRUE) {
+    Status = FdtGetNextCondNodeInBranch (
+               Fdt,
+               FdtBranch,
+               NodeChecker,
+               Context,
+               &CurrNode
+               );
+    if (EFI_ERROR (Status)  &&
+        (Status != EFI_NOT_FOUND)) {
+      ASSERT (0);
+      return Status;
+    } else if (Status == EFI_NOT_FOUND) {
+      break;
+    }
+    (*NodeCount)++;
+  }
+  return EFI_SUCCESS;
+}
+
+/** Count the number of nodes in a branch with the input name.
+
+  @param [in]  Fdt              Pointer to a Flattened Device Tree.
+  @param [in]  FdtBranch        Only search in the sub-nodes of this branch.
+                                Write (-1) to search the whole tree.
+  @param [in]  NodeName         Node name to search.
+                                This is a NULL terminated string.
+  @param [out] NodeCount        If success, contains the count of nodes
+                                fulfilling the condition.
+                                Can be 0.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_ABORTED             An error occurred.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FdtCountNamedNodeInBranch (
+  IN  CONST VOID    * Fdt,
+  IN        INT32     FdtBranch,
+  IN  CONST CHAR8   * NodeName,
+  OUT       UINT32  * NodeCount
+  )
+{
+  return FdtCountCondNodeInBranch (
+           Fdt,
+           FdtBranch,
+           FdtNodeHasName,
+           NodeName,
+           NodeCount
+           );
+}
+
+/** Count the number of nodes in a branch with at least
+    one compatible property.
+
+  @param [in]  Fdt              Pointer to a Flattened Device Tree.
+  @param [in]  FdtBranch        Only search in the sub-nodes of this branch.
+                                Write (-1) to search the whole tree.
+  @param [in]  CompatNamesInfo  Table of compatible strings to
+                                compare with the compatible property
+                                of the node.
+  @param [out] NodeCount        If success, contains the count of nodes
+                                fulfilling the condition.
+                                Can be 0.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_ABORTED             An error occurred.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FdtCountCompatNodeInBranch (
+  IN  CONST VOID                * Fdt,
+  IN        INT32                 FdtBranch,
+  IN  CONST COMPATIBILITY_INFO  * CompatNamesInfo,
+  OUT       UINT32              * NodeCount
+  )
+{
+  return FdtCountCondNodeInBranch (
+           Fdt,
+           FdtBranch,
+           FdtNodeIsCompatible,
+           CompatNamesInfo,
+           NodeCount
+           );
+}
+
+/** Count the number of nodes in a branch having the PropName property.
+
+  @param [in]  Fdt              Pointer to a Flattened Device Tree.
+  @param [in]  FdtBranch        Only search in the sub-nodes of this branch.
+                                Write (-1) to search the whole tree.
+  @param [in]  PropName         Name of the property to search.
+                                This is a NULL terminated string.
+  @param [out] NodeCount        If success, contains the count of nodes
+                                fulfilling the condition.
+                                Can be 0.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_ABORTED             An error occurred.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FdtCountPropNodeInBranch (
+  IN  CONST VOID      * Fdt,
+  IN        INT32       FdtBranch,
+  IN  CONST CHAR8     * PropName,
+  OUT       UINT32    * NodeCount
+  )
+{
+  return FdtCountCondNodeInBranch (
+           Fdt,
+           FdtBranch,
+           FdtNodeHasProperty,
+           PropName,
+           NodeCount
+           );
+}
+
+/** Get the interrupt-controller node handling the interrupts of
+    the input node.
+
+  To do this, recursively search a node with either the "interrupt-controller"
+  or the "interrupt-parent" property in the parents of Node.
+
+  Devicetree Specification, Release v0.3,
+  2.4.1 "Properties for Interrupt Generating Devices":
+    Because the hierarchy of the nodes in the interrupt tree
+    might not match the devicetree, the interrupt-parent
+    property is available to make the definition of an
+    interrupt parent explicit. The value is the phandle to the
+    interrupt parent. If this property is missing from a
+    device, its interrupt parent is assumed to be its devicetree
+    parent.
+
+  @param [in]  Fdt              Pointer to a Flattened Device Tree.
+  @param [in]  Node             Offset of the node to start the search.
+  @param [out] IntcNode         If success, contains the offset of the
+                                interrupt-controller node.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_NOT_FOUND           No interrupt-controller node found.
+  @retval EFI_ABORTED             An error occurred.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetIntcParentNode (
+  IN  CONST VOID    * Fdt,
+  IN        INT32     Node,
+  OUT       INT32   * IntcNode
+  )
+{
+  CONST UINT32  * PHandle;
+  INT32           Size;
+  CONST VOID    * Prop;
+
+  if ((Fdt == NULL) ||
+      (IntcNode == NULL)) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  while (TRUE) {
+    // Check whether the node has the "interrupt-controller" property.
+    Prop = fdt_getprop (Fdt, Node, "interrupt-controller", &Size);
+    if ((Prop != NULL) && (Size >= 0)) {
+      // The interrupt-controller has been found.
+      *IntcNode = Node;
+      return EFI_SUCCESS;
+    } else {
+      // Check whether the node has the "interrupt-parent" property.
+      PHandle = fdt_getprop (Fdt, Node, "interrupt-parent", &Size);
+      if ((PHandle != NULL) && (Size == sizeof (UINT32))) {
+        // The phandle of the interrupt-controller has been found.
+        // Search the node having this phandle and return it.
+        Node = fdt_node_offset_by_phandle (Fdt, fdt32_to_cpu (*PHandle));
+        if (Node < 0) {
+          ASSERT (0);
+          return EFI_ABORTED;
+        }
+
+        *IntcNode = Node;
+        return EFI_SUCCESS;
+      } else if (Size != -FDT_ERR_NOTFOUND) {
+        ASSERT (0);
+        return EFI_ABORTED;
+      }
+    }
+
+    if (Node == 0) {
+      // We are at the root of the tree. Not parent available.
+      return EFI_NOT_FOUND;
+    }
+
+    // Get the parent of the node.
+    Node = fdt_parent_offset (Fdt, Node);
+    if (Node < 0) {
+      // An error occurred.
+      ASSERT (0);
+      return EFI_ABORTED;
+    }
+  } // while
+}
+
+/** Get the "interrupt-cells" property value of the node.
+
+  The "interrupts" property requires to know the number of cells used
+  to encode an interrupt. This information is stored in the
+  interrupt-controller of the input Node.
+
+  @param [in]  Fdt          Pointer to a Flattened Device Tree (Fdt).
+  @param [in]  IntcNode     Offset of an interrupt-controller node.
+  @param [out] IntCells     If success, contains the "interrupt-cells"
+                            property of the IntcNode.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_UNSUPPORTED         Unsupported.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetInterruptCellsInfo (
+  IN  CONST VOID      * Fdt,
+  IN        INT32       IntcNode,
+  OUT       INT32     * IntCells
+  )
+{
+  CONST UINT32  * Data;
+  INT32           Size;
+
+  if ((Fdt == NULL) ||
+      (IntCells == NULL)) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Data = fdt_getprop (Fdt, IntcNode, "#interrupt-cells", &Size);
+  if ((Data == NULL) || (Size != sizeof (UINT32))) {
+    // If error or not on one UINT32 cell.
+    ASSERT (0);
+    return EFI_ABORTED;
+  }
+
+  *IntCells = fdt32_to_cpu (*Data);
+
+  return EFI_SUCCESS;
+}
+
+/** Get the "#address-cells" and/or "#size-cells" property of the node.
+
+  According to the Device Tree specification, s2.3.5 "#address-cells and
+  #size-cells":
+  "If missing, a client program should assume a default value of 2 for
+  #address-cells, and a value of 1 for #size-cells."
+
+  @param [in]  Fdt              Pointer to a Flattened Device Tree.
+  @param [in]  Node             Offset of the node having to get the
+                                "#address-cells" and "#size-cells"
+                                properties from.
+  @param [out] AddressCells     If success, number of address-cells.
+                                If the property is not available,
+                                default value is 2.
+  @param [out] SizeCells        If success, number of size-cells.
+                                If the property is not available,
+                                default value is 1.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_ABORTED             An error occurred.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetAddressInfo (
+  IN  CONST VOID      * Fdt,
+  IN        INT32       Node,
+  OUT       INT32     * AddressCells,   OPTIONAL
+  OUT       INT32     * SizeCells       OPTIONAL
+  )
+{
+  if (Fdt == NULL) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (AddressCells != NULL) {
+    *AddressCells = fdt_address_cells (Fdt, Node);
+    if (*AddressCells < 0) {
+      ASSERT (0);
+      return EFI_ABORTED;
+    }
+  }
+
+  if (SizeCells != NULL) {
+    *SizeCells = fdt_size_cells (Fdt, Node);
+    if (*SizeCells < 0) {
+      ASSERT (0);
+      return EFI_ABORTED;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/** Get the "#address-cells" and/or "#size-cells" property of the parent node.
+
+  According to the Device Tree specification, s2.3.5 "#address-cells and
+  #size-cells":
+  "If missing, a client program should assume a default value of 2 for
+  #address-cells, and a value of 1 for #size-cells."
+
+  @param [in]  Fdt              Pointer to a Flattened Device Tree.
+  @param [in]  Node             Offset of the node having to get the
+                                "#address-cells" and "#size-cells"
+                                properties from its parent.
+  @param [out] AddressCells     If success, number of address-cells.
+                                If the property is not available,
+                                default value is 2.
+  @param [out] SizeCells        If success, number of size-cells.
+                                If the property is not available,
+                                default value is 1.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_ABORTED             An error occurred.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetParentAddressInfo (
+  IN  CONST VOID      * Fdt,
+  IN        INT32       Node,
+  OUT       INT32     * AddressCells,   OPTIONAL
+  OUT       INT32     * SizeCells       OPTIONAL
+  )
+{
+  if (Fdt == NULL) {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Node = fdt_parent_offset (Fdt, Node);
+  if (Node < 0) {
+    // End of the tree, or an error occurred.
+    ASSERT (0);
+    return EFI_ABORTED;
+  }
+
+  return FdtGetAddressInfo (Fdt, Node, AddressCells, SizeCells);
+}
diff --git a/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.h b/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.h
new file mode 100644
index 000000000000..0076c5066d4c
--- /dev/null
+++ b/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.h
@@ -0,0 +1,458 @@
+/** @file
+  Flattened device tree utility.
+
+  Copyright (c) 2021, ARM Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Reference(s):
+  - Device tree Specification - Release v0.3
+  - linux/Documentation/devicetree/bindings/interrupt-controller/arm%2Cgic.yaml
+  - linux//Documentation/devicetree/bindings/interrupt-controller/arm%2Cgic.yaml
+**/
+
+#ifndef FDT_UTILITY_H_
+#define FDT_UTILITY_H_
+
+/** Get the offset of an address in a "reg" Device Tree property.
+
+  In a Device Tree, the "reg" property stores address/size couples.
+  They are stored on N 32-bits cells.
+  Based on the value of the #address-cells, the #size-cells and the
+  index in the "reg" property, compute the number of 32-bits cells
+  to skip.
+
+  @param [in]  Index        Index in the reg property.
+  @param [in]  AddrCells    Number of cells used to store an address.
+  @param [in]  SizeCells    Number of cells used to store the size of
+                            an address.
+
+  @retval  Number of 32-bits cells to skip to access the address.
+*/
+#define GET_DT_REG_ADDRESS_OFFSET(Index, AddrCells, SizeCells) (            \
+          (Index) * ((AddrCells) + (SizeCells))                             \
+          )
+
+/** Get the offset of an address size in a "reg" Device Tree property.
+
+  In a Device Tree, the "reg" property stores address/size couples.
+  They are stored on N 32-bits cells.
+  Based on the value of the #address-cells, the #size-cells and the
+  index in the "reg" property, compute the number of 32-bits cells
+  to skip.
+
+  @param [in]  Index        Index in the reg property.
+  @param [in]  AddrCells    Number of cells used to store an address.
+  @param [in]  SizeCells    Number of cells used to store the size of
+                            an address.
+
+  @retval  Number of 32-bits cells to skip to access the address size.
+*/
+#define GET_DT_REG_SIZE_OFFSET(Index, AddrCells, SizeCells)  (              \
+          GET_DT_REG_ADDRESS_OFFSET ((Index), (AddrCells), (SizeCells)) +   \
+          (SizeCells)                                                       \
+          )
+
+/// Maximum string length for compatible names.
+#define COMPATIBLE_STR_LEN             (32U)
+
+/// Interrupt macros
+#define PPI_OFFSET                     (16U)
+#define SPI_OFFSET                     (32U)
+#define DT_PPI_IRQ                     (1U)
+#define DT_SPI_IRQ                     (0U)
+#define DT_IRQ_IS_EDGE_TRIGGERED(x)    ((((x) & (BIT0 | BIT2)) != 0))
+#define DT_IRQ_IS_ACTIVE_LOW(x)        ((((x) & (BIT1 | BIT3)) != 0))
+#define IRQ_TYPE_OFFSET                (0U)
+#define IRQ_NUMBER_OFFSET              (1U)
+#define IRQ_FLAGS_OFFSET               (2U)
+
+/** Get the interrupt Id of an interrupt described in a fdt.
+
+  Data must describe a GIC interrupt. A GIC interrupt is on at least
+  3 UINT32 cells.
+  This function DOES NOT SUPPORT extended SPI range and extended PPI range.
+
+  @param [in]  Data   Pointer to the first cell of an "interrupts" property.
+
+  @retval  The interrupt id.
+**/
+UINT32
+EFIAPI
+FdtGetInterruptId (
+  UINT32 CONST  * Data
+  );
+
+/** Get the ACPI interrupt flags of an interrupt described in a fdt.
+
+  Data must describe a GIC interrupt. A GIC interrupt is on at least
+  3 UINT32 cells.
+
+  @param [in]  Data   Pointer to the first cell of an "interrupts" property.
+
+  @retval  The interrupt flags (for ACPI).
+**/
+UINT32
+EFIAPI
+FdtGetInterruptFlags (
+  UINT32 CONST  * Data
+  );
+
+/** A structure describing a compatibility string.
+*/
+typedef struct CompatStr {
+  CONST CHAR8 CompatStr[COMPATIBLE_STR_LEN];
+} COMPATIBILITY_STR;
+
+/** Structure containing a list of compatible names and their count.
+*/
+typedef struct CompatibilityInfo {
+  /// Count of entries in the NAME_TABLE.
+  UINT32                     Count;
+
+  /// Pointer to a table storing the names.
+  CONST COMPATIBILITY_STR  * CompatTable;
+} COMPATIBILITY_INFO;
+
+/** Operate a check on a Device Tree node.
+
+  @param [in]  Fdt          Pointer to a Flattened Device Tree.
+  @param [in]  NodeOffset   Offset of the node to compare input string.
+  @param [in]  Context      Context to operate the check on the node.
+
+  @retval True    The check is correct.
+  @retval FALSE   Otherwise, or error.
+**/
+typedef
+BOOLEAN
+(EFIAPI *NODE_CHECKER_FUNC) (
+  IN  CONST VOID    * Fdt,
+  IN        INT32     NodeOffset,
+  IN  CONST VOID    * Context
+  );
+
+/** Iterate through the list of strings in the Context,
+    and check whether at least one string is matching the
+    "compatible" property of the node.
+
+  @param [in]  Fdt          Pointer to a Flattened Device Tree.
+  @param [in]  Node         Offset of the node to operate the check on.
+  @param [in]  CompatInfo   COMPATIBILITY_INFO containing the list of compatible
+                            strings to compare with the "compatible" property
+                            of the node.
+
+  @retval TRUE    At least one string matched, the node is compatible.
+  @retval FALSE   Otherwise, or error.
+**/
+BOOLEAN
+EFIAPI
+FdtNodeIsCompatible (
+  IN  CONST VOID                * Fdt,
+  IN        INT32                 Node,
+  IN  CONST VOID                * CompatInfo
+  );
+
+/** Check whether a node has a property.
+
+  @param [in]  Fdt          Pointer to a Flattened Device Tree.
+  @param [in]  Node         Offset of the node to operate the check on.
+  @param [in]  PropertyName Name of the property to search.
+                            This is a NULL terminated string.
+
+  @retval True    The node has the property.
+  @retval FALSE   Otherwise, or error.
+**/
+BOOLEAN
+EFIAPI
+FdtNodeHasProperty (
+  IN  CONST VOID  * Fdt,
+  IN        INT32   Node,
+  IN  CONST VOID * PropertyName
+  );
+
+/** Get the next node in a branch having a matching name.
+
+  The Device tree is traversed in a depth-first search, starting from Node.
+  The input Node is skipped.
+
+  @param [in]       Fdt         Pointer to a Flattened Device Tree.
+  @param [in]       FdtBranch   Only search in the sub-nodes of this branch.
+                                Write (-1) to search the whole tree.
+  @param [in]       NodeName    The node name to search.
+                                This is a NULL terminated string.
+  @param [in, out]  Node        At entry: Node offset to start the search.
+                                          This first node is skipped.
+                                          Write (-1) to search the whole tree.
+                                At exit:  If success, contains the offset of
+                                          the next node in the branch
+                                          having a matching name.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_ABORTED             An error occurred.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_NOT_FOUND           No matching node found.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetNextNamedNodeInBranch (
+  IN      CONST VOID    * Fdt,
+  IN            INT32     FdtBranch,
+  IN      CONST CHAR8   * NodeName,
+  IN OUT        INT32   * Node
+  );
+
+/** Get the next node in a branch with at least one compatible property.
+
+  The Device tree is traversed in a depth-first search, starting from Node.
+  The input Node is skipped.
+
+  @param [in]       Fdt         Pointer to a Flattened Device Tree.
+  @param [in]       FdtBranch   Only search in the sub-nodes of this branch.
+                                Write (-1) to search the whole tree.
+  @param [in]  CompatNamesInfo  Table of compatible strings to compare with
+                                the compatible property of the node.
+  @param [in, out]  Node        At entry: Node offset to start the search.
+                                          This first node is skipped.
+                                          Write (-1) to search the whole tree.
+                                At exit:  If success, contains the offset of
+                                          the next node in the branch
+                                          being compatible.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_ABORTED             An error occurred.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_NOT_FOUND           No matching node found.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetNextCompatNodeInBranch (
+  IN      CONST VOID                * Fdt,
+  IN            INT32                 FdtBranch,
+  IN      CONST COMPATIBILITY_INFO  * CompatNamesInfo,
+  IN OUT        INT32               * Node
+  );
+
+/** Get the next node in a branch having the PropName property.
+
+  The Device tree is traversed in a depth-first search, starting from Node.
+  The input Node is skipped.
+
+  @param [in]       Fdt         Pointer to a Flattened Device Tree.
+  @param [in]       FdtBranch   Only search in the sub-nodes of this branch.
+                                Write (-1) to search the whole tree.
+  @param [in]       PropName    Name of the property to search.
+                                This is a NULL terminated string.
+  @param [in, out]  Node        At entry: Node offset to start the search.
+                                          This first node is skipped.
+                                          Write (-1) to search the whole tree.
+                                At exit:  If success, contains the offset of
+                                          the next node in the branch
+                                          being compatible.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_ABORTED             An error occurred.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_NOT_FOUND           No matching node found.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetNextPropNodeInBranch (
+  IN      CONST VOID    * Fdt,
+  IN            INT32     FdtBranch,
+  IN      CONST CHAR8   * PropName,
+  IN OUT        INT32   * Node
+  );
+
+/** Count the number of nodes in a branch with the input name.
+
+  @param [in]  Fdt              Pointer to a Flattened Device Tree.
+  @param [in]  FdtBranch        Only search in the sub-nodes of this branch.
+                                Write (-1) to search the whole tree.
+  @param [in]  NodeName         Node name to search.
+                                This is a NULL terminated string.
+  @param [out] NodeCount        If success, contains the count of nodes
+                                fulfilling the condition.
+                                Can be 0.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_ABORTED             An error occurred.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FdtCountNamedNodeInBranch (
+  IN  CONST VOID    * Fdt,
+  IN        INT32     FdtBranch,
+  IN  CONST CHAR8   * NodeName,
+  OUT       UINT32  * NodeCount
+  );
+
+/** Count the number of nodes in a branch with at least
+    one compatible property.
+
+  @param [in]  Fdt              Pointer to a Flattened Device Tree.
+  @param [in]  FdtBranch        Only search in the sub-nodes of this branch.
+                                Write (-1) to search the whole tree.
+  @param [in]  CompatibleTable  Table of compatible strings to
+                                compare with the compatible property
+                                of the node.
+  @param [out] NodeCount        If success, contains the count of nodes
+                                fulfilling the condition.
+                                Can be 0.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_ABORTED             An error occurred.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FdtCountCompatNodeInBranch (
+  IN  CONST VOID                * Fdt,
+  IN        INT32                 FdtBranch,
+  IN  CONST COMPATIBILITY_INFO  * CompatNamesInfo,
+  OUT       UINT32              * NodeCount
+  );
+
+/** Count the number of nodes in a branch having the PropName property.
+
+  @param [in]  Fdt              Pointer to a Flattened Device Tree.
+  @param [in]  FdtBranch        Only search in the sub-nodes of this branch.
+                                Write (-1) to search the whole tree.
+  @param [in]  PropName         Name of the property to search.
+                                This is a NULL terminated string.
+  @param [out] NodeCount        If success, contains the count of nodes
+                                fulfilling the condition.
+                                Can be 0.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_ABORTED             An error occurred.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FdtCountPropNodeInBranch (
+  IN  CONST VOID      * Fdt,
+  IN        INT32       FdtBranch,
+  IN  CONST CHAR8     * PropName,
+  OUT       UINT32    * NodeCount
+  );
+
+/** Get the interrupt-controller node handling the interrupts of
+    the input node.
+
+  To do this, recursively search a node with either the "interrupt-controller"
+  or the "interrupt-parent" property in the parents of Node.
+
+  Devicetree Specification, Release v0.3,
+  2.4.1 "Properties for Interrupt Generating Devices":
+    Because the hierarchy of the nodes in the interrupt tree
+    might not match the devicetree, the interrupt-parent
+    property is available to make the definition of an
+    interrupt parent explicit. The value is the phandle to the
+    interrupt parent. If this property is missing from a
+    device, its interrupt parent is assumed to be its devicetree
+    parent.
+
+  @param [in]  Fdt              Pointer to a Flattened Device Tree.
+  @param [in]  Node             Offset of the node to start the search.
+  @param [out] IntcNode         If success, contains the offset of the
+                                interrupt-controller node.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_NOT_FOUND           No interrupt-controller node found.
+  @retval EFI_ABORTED             An error occurred.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetIntcParentNode (
+  IN  CONST VOID    * Fdt,
+  IN        INT32     Node,
+  OUT       INT32   * IntcNode
+  );
+
+/** Get the "interrupt-cells" property value of the node.
+
+  The "interrupts" property requires to know the number of cells used
+  to encode an interrupt. This information is stored in the
+  interrupt-controller of the input Node.
+
+  @param [in]  Fdt          Pointer to a Flattened Device Tree (Fdt).
+  @param [in]  IntcNode     Offset of an interrupt-controller node.
+  @param [out] IntCells     If success, contains the "interrupt-cells"
+                            property of the IntcNode.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+  @retval EFI_UNSUPPORTED         Unsupported.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetInterruptCellsInfo (
+  IN  CONST VOID      * Fdt,
+  IN        INT32       IntcNode,
+  OUT       INT32     * InterruptCells
+  );
+
+/** Get the "#address-cells" and/or "#size-cells" property of the node.
+
+  According to the Device Tree specification, s2.3.5 "#address-cells and
+  #size-cells":
+  "If missing, a client program should assume a default value of 2 for
+  #address-cells, and a value of 1 for #size-cells."
+
+  @param [in]  Fdt              Pointer to a Flattened Device Tree.
+  @param [in]  Node             Offset of the node having to get the
+                                "#address-cells" and "#size-cells"
+                                properties from.
+  @param [out] AddressCells     If success, number of address-cells.
+                                If the property is not available,
+                                default value is 2.
+  @param [out] SizeCells        If success, number of size-cells.
+                                If the property is not available,
+                                default value is 1.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_ABORTED             An error occurred.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetAddressInfo (
+  IN  CONST VOID      * Fdt,
+  IN        INT32       Node,
+  OUT       INT32     * AddressCells,   OPTIONAL
+  OUT       INT32     * SizeCells       OPTIONAL
+  );
+
+/** Get the "#address-cells" and/or "#size-cells" property of the parent node.
+
+  According to the Device Tree specification, s2.3.5 "#address-cells and
+  #size-cells":
+  "If missing, a client program should assume a default value of 2 for
+  #address-cells, and a value of 1 for #size-cells."
+
+  @param [in]  Fdt              Pointer to a Flattened Device Tree.
+  @param [in]  Node             Offset of the node having to get the
+                                "#address-cells" and "#size-cells"
+                                properties from its parent.
+  @param [out] AddressCells     If success, number of address-cells.
+                                If the property is not available,
+                                default value is 2.
+  @param [out] SizeCells        If success, number of size-cells.
+                                If the property is not available,
+                                default value is 1.
+
+  @retval EFI_SUCCESS             The function completed successfully.
+  @retval EFI_ABORTED             An error occurred.
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetParentAddressInfo (
+  IN  CONST VOID      * Fdt,
+  IN        INT32       Node,
+  OUT       INT32     * AddressCells,   OPTIONAL
+  OUT       INT32     * SizeCells       OPTIONAL
+  );
+
+#endif // FDT_UTILITY_H_
-- 
2.17.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#76970): https://edk2.groups.io/g/devel/message/76970
Mute This Topic: https://groups.io/mt/83736624/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-


Re: [edk2-devel] [PATCH v1 03/14] DynamicTablesPkg: FdtHwInfoParser: Add FDT utility functions
Posted by Sami Mujawar 4 years, 3 months ago
Hi Pierre,

I have a minor comment, otherwise this patch looks good to me.

Regards,

Sami Mujawar

On 23/06/2021 01:38 PM, Pierre.Gondois@arm.com wrote:
> From: Pierre Gondois <Pierre.Gondois@arm.com>
>
> The FdtHwInfoParser parses a platform Device Tree and populates
> the Platform Information repository with Configuration Manager
> objects.
>
> Therefore, add a set of helper functions to simplify parsing of
> the platform Device Tree.
>
> Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
> Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
> ---
>   .../Library/FdtHwInfoParserLib/FdtUtility.c   | 909 ++++++++++++++++++
>   .../Library/FdtHwInfoParserLib/FdtUtility.h   | 458 +++++++++
>   2 files changed, 1367 insertions(+)
>   create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.c
>   create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.h
>
> diff --git a/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.c b/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.c
> new file mode 100644
> index 000000000000..0fca82aedf9e
> --- /dev/null
> +++ b/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.c
> @@ -0,0 +1,909 @@
> +/** @file
> +  Flattened device tree utility.
> +
> +  Copyright (c) 2021, ARM Limited. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +  @par Reference(s):
> +  - Device tree Specification - Release v0.3
> +  - linux/Documentation/devicetree/bindings/interrupt-controller/arm%2Cgic.yaml
> +  - linux//Documentation/devicetree/bindings/interrupt-controller/arm%2Cgic.yaml
> +**/
> +
> +#include <FdtHwInfoParserInclude.h>
> +#include "FdtUtility.h"
> +
> +/** Get the interrupt Id of an interrupt described in a fdt.
> +
> +  Data must describe a GIC interrupt. A GIC interrupt is on at least
> +  3 UINT32 cells.
> +  This function DOES NOT SUPPORT extended SPI range and extended PPI range.
> +
> +  @param [in]  Data   Pointer to the first cell of an "interrupts" property.
> +
> +  @retval  The interrupt id.
> +**/
> +UINT32
> +EFIAPI
> +FdtGetInterruptId (
> +  UINT32 CONST  * Data
> +  )
> +{
> +  UINT32  IrqType;
> +  UINT32  IrqId;
> +
> +  ASSERT (Data != NULL);
> +
> +  IrqType = fdt32_to_cpu (Data[IRQ_TYPE_OFFSET]);
> +  IrqId = fdt32_to_cpu (Data[IRQ_NUMBER_OFFSET]);
> +
> +  switch (IrqType) {
> +  case DT_SPI_IRQ:
> +    IrqId += SPI_OFFSET;
> +    break;
> +
> +  case DT_PPI_IRQ:
> +    IrqId += PPI_OFFSET;
> +    break;
> +
> +  default:
> +    ASSERT (0);
> +    IrqId = 0;
> +  }
> +
> +  return IrqId;
> +}
> +
> +/** Get the ACPI interrupt flags of an interrupt described in a fdt.
> +
> +  Data must describe a GIC interrupt. A GIC interrupt is on at least
> +  3 UINT32 cells.
> +
> +  PPI interrupt cpu mask on bits [15:8] are ignored.
> +
> +  @param [in]  Data   Pointer to the first cell of an "interrupts" property.
> +
> +  @retval  The interrupt flags (for ACPI).
> +**/
> +UINT32
> +EFIAPI
> +FdtGetInterruptFlags (
> +  UINT32 CONST  * Data
> +  )
> +{
> +  UINT32  IrqFlags;
> +  UINT32  AcpiIrqFlags;
> +
> +  ASSERT (Data != NULL);
> +
> +  IrqFlags = fdt32_to_cpu (Data[IRQ_FLAGS_OFFSET]);
> +
> +  AcpiIrqFlags = DT_IRQ_IS_EDGE_TRIGGERED (IrqFlags) ? BIT0 : 0;
> +  AcpiIrqFlags |= DT_IRQ_IS_ACTIVE_LOW (IrqFlags) ? BIT1 : 0;
> +
> +  return AcpiIrqFlags;
> +}
> +
> +/** Check whether a node has the input name.
> +
> +  @param [in]  Fdt          Pointer to a Flattened Device Tree.
> +  @param [in]  Node         Offset of the node to check the name.
> +  @param [in]  SearchName   Node name to search.
> +                            This is a NULL terminated string.
> +
> +  @retval True    The node has the input name.
> +  @retval FALSE   Otherwise, or error.
> +**/
> +STATIC
> +BOOLEAN
> +EFIAPI
> +FdtNodeHasName (
> +  IN  CONST VOID  * Fdt,
> +  IN        INT32   Node,
> +  IN  CONST VOID  * SearchName
> +  )
> +{
> +  CONST CHAR8   * NodeName;
> +  UINT32          Length;
> +
> +  if ((Fdt == NULL) ||
> +      (SearchName == NULL)) {
> +    ASSERT (0);
> +    return FALSE;
> +  }
> +
> +  // Always compare the whole string. Don't stop at the "@" char.
> +  Length = (UINT32)AsciiStrLen (SearchName);
> +
> +  // Get the address of the node name.
> +  NodeName = fdt_offset_ptr (Fdt, Node + FDT_TAGSIZE, Length + 1);
> +  if (NodeName == NULL) {
> +    return FALSE;
> +  }
> +
> +  // SearchName must be longer than the node name.
> +  if (Length > AsciiStrLen (NodeName)) {
> +    return FALSE;
> +  }
> +
> +  // Use CompareMem here instead of AsciiStrnCmp as the NodeName
[SAMI] I think the comment here needs to be updated.
> +  // may contain the node name followed by '@'0x<addr>.
> +  if (AsciiStrnCmp (NodeName, SearchName, Length) != 0) {
> +    return FALSE;
> +  }
> +
> +  // The name matches perfectly, or
> +  // the node name is XXX@addr and the XXX matches.
> +  if ((NodeName[Length] == '\0') ||
> +      (NodeName[Length] == '@')) {
> +    return TRUE;
> +  }
> +
> +  return FALSE;
> +}
> +
> +/** Iterate through the list of strings in the Context,
> +    and check whether at least one string is matching the
> +    "compatible" property of the node.
> +
> +  @param [in]  Fdt          Pointer to a Flattened Device Tree.
> +  @param [in]  Node         Offset of the node to operate the check on.
> +  @param [in]  CompatInfo   COMPATIBILITY_INFO containing the list of compatible
> +                            strings to compare with the "compatible" property
> +                            of the node.
> +
> +  @retval TRUE    At least one string matched, the node is compatible.
> +  @retval FALSE   Otherwise, or error.
> +**/
> +BOOLEAN
> +EFIAPI
> +FdtNodeIsCompatible (
> +  IN  CONST VOID                * Fdt,
> +  IN        INT32                 Node,
> +  IN  CONST VOID                * CompatInfo
> +  )
> +{
> +  UINT32                      Index;
> +  CONST COMPATIBILITY_STR   * CompatibleTable;
> +  UINT32                      Count;
> +  CONST VOID                * Prop;
> +  INT32                       PropLen;
> +
> +  if ((Fdt == NULL) ||
> +      (CompatInfo == NULL)) {
> +    ASSERT (0);
> +    return FALSE;
> +  }
> +
> +  Count = ((COMPATIBILITY_INFO*)CompatInfo)->Count;
> +  CompatibleTable = ((COMPATIBILITY_INFO*)CompatInfo)->CompatTable;
> +
> +  // Get the "compatible" property.
> +  Prop = fdt_getprop (Fdt, Node, "compatible", &PropLen);
> +  if ((Prop == NULL) || (PropLen < 0)) {
> +    return FALSE;
> +  }
> +
> +  for (Index = 0; Index < Count; Index++) {
> +    if (fdt_stringlist_contains (
> +           Prop,
> +           PropLen,
> +           CompatibleTable[Index].CompatStr
> +           )) {
> +      return TRUE;
> +    }
> +  } // for
> +
> +  return FALSE;
> +}
> +
> +/** Check whether a node has a property.
> +
> +  @param [in]  Fdt          Pointer to a Flattened Device Tree.
> +  @param [in]  Node         Offset of the node to operate the check on.
> +  @param [in]  PropertyName Name of the property to search.
> +                            This is a NULL terminated string.
> +
> +  @retval True    The node has the property.
> +  @retval FALSE   Otherwise, or error.
> +**/
> +BOOLEAN
> +EFIAPI
> +FdtNodeHasProperty (
> +  IN  CONST VOID  * Fdt,
> +  IN        INT32   Node,
> +  IN  CONST VOID  * PropertyName
> +  )
> +{
> +  INT32         Size;
> +  CONST VOID  * Prop;
> +
> +  if ((Fdt == NULL) ||
> +      (PropertyName == NULL)) {
> +    ASSERT (0);
> +    return FALSE;
> +  }
> +
> +  Prop = fdt_getprop (Fdt, Node, PropertyName, &Size);
> +  if ((Prop == NULL) || (Size < 0)) {
> +    return FALSE;
> +  }
> +  return TRUE;
> +}
> +
> +/** Get the next node in the whole DT fulfilling a condition.
> +
> +  The condition to fulfill is checked by the NodeChecker function.
> +  Context is passed to NodeChecker.
> +
> +  The Device tree is traversed in a depth-first search, starting from Node.
> +  The input Node is skipped.
> +
> +  @param [in]  Fdt              Pointer to a Flattened Device Tree.
> +  @param [in, out]  Node        At entry: Node offset to start the search.
> +                                          This first node is skipped.
> +                                          Write (-1) to search the whole tree.
> +                                At exit:  If success, contains the offset of
> +                                          the next node fulfilling the
> +                                          condition.
> +  @param [in, out]  Depth       Depth is incremented/decremented of the depth
> +                                difference between the input Node and the
> +                                output Node.
> +                                E.g.: If the output Node is a child node
> +                                of the input Node, contains (+1).
> +  @param [in]  NodeChecker      Function called to check if the condition
> +                                is fulfilled.
> +  @param [in]  Context          Context for the NodeChecker.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_ABORTED             An error occurred.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_NOT_FOUND           No matching node found.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +FdtGetNextCondNode (
> +  IN      CONST VOID              * Fdt,
> +  IN OUT        INT32             * Node,
> +  IN OUT        INT32             * Depth,
> +  IN            NODE_CHECKER_FUNC   NodeChecker,
> +  IN      CONST VOID              * Context
> +  )
> +{
> +  INT32   CurrNode;
> +
> +  if ((Fdt == NULL)   ||
> +      (Node == NULL)  ||
> +      (Depth == NULL) ||
> +      (NodeChecker == NULL)) {
> +    ASSERT (0);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  CurrNode = *Node;
> +  do {
> +    CurrNode = fdt_next_node (Fdt, CurrNode, Depth);
> +    if ((CurrNode == -FDT_ERR_NOTFOUND) ||
> +        (*Depth < 0)) {
> +      // End of the tree, no matching node found.
> +      return EFI_NOT_FOUND;
> +    } else if (CurrNode < 0) {
> +      // An error occurred.
> +      ASSERT (0);
> +      return EFI_ABORTED;
> +    }
> +  }  while (!NodeChecker (Fdt, CurrNode, Context));
> +
> +  // Matching node found.
> +  *Node = CurrNode;
> +  return EFI_SUCCESS;
> +}
> +
> +/** Get the next node in a branch fulfilling a condition.
> +
> +  The condition to fulfill is checked by the NodeChecker function.
> +  Context is passed to NodeChecker.
> +
> +  The Device tree is traversed in a depth-first search, starting from Node.
> +  The input Node is skipped.
> +
> +  @param [in]       Fdt             Pointer to a Flattened Device Tree.
> +  @param [in]       FdtBranch       Only search in the sub-nodes of this
> +                                    branch.
> +                                    Write (-1) to search the whole tree.
> +  @param [in]       NodeChecker     Function called to check if the condition
> +                                    is fulfilled.
> +  @param [in]       Context         Context for the NodeChecker.
> +  @param [in, out]  Node            At entry: Node offset to start the search.
> +                                         This first node is skipped.
> +                                         Write (-1) to search the whole tree.
> +                                    At exit:  If success, contains the offset
> +                                         of the next node in the branch
> +                                         fulfilling the condition.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_ABORTED             An error occurred.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_NOT_FOUND           No matching node found.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +FdtGetNextCondNodeInBranch (
> +  IN      CONST VOID              * Fdt,
> +  IN            INT32               FdtBranch,
> +  IN            NODE_CHECKER_FUNC   NodeChecker,
> +  IN      CONST VOID              * Context,
> +  IN OUT        INT32             * Node
> +  )
> +{
> +  EFI_STATUS    Status;
> +  INT32         CurrNode;
> +  INT32         Depth;
> +
> +  if ((Fdt == NULL)   ||
> +      (Node == NULL)  ||
> +      (NodeChecker == NULL)) {
> +    ASSERT (0);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  CurrNode = FdtBranch;
> +  Depth = 0;
> +
> +  // First, check the Node is in the sub-nodes of the branch.
> +  // This allows to find the relative depth of Node in the branch.
> +  if (CurrNode != *Node) {
> +    for (CurrNode = fdt_next_node (Fdt, CurrNode, &Depth);
> +         (CurrNode >= 0) && (Depth > 0);
> +         CurrNode = fdt_next_node (Fdt, CurrNode, &Depth)) {
> +      if (CurrNode == *Node) {
> +        // Node found.
> +        break;
> +      }
> +    } // for
> +
> +    if ((CurrNode < 0) || (Depth <= 0)) {
> +      // Node is not a node in the branch, or an error occurred.
> +      ASSERT (0);
> +      return EFI_INVALID_PARAMETER;
> +    }
> +  }
> +
> +  // Get the next node in the tree fulfilling the condition,
> +  // in any branch.
> +  Status = FdtGetNextCondNode (
> +             Fdt,
> +             Node,
> +             &Depth,
> +             NodeChecker,
> +             Context
> +             );
> +  if (EFI_ERROR (Status)) {
> +    ASSERT (Status == EFI_NOT_FOUND);
> +    return Status;
> +  }
> +
> +  if (Depth <= 0) {
> +    // The node found is not in the right branch.
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** Get the next node in a branch having a matching name.
> +
> +  The Device tree is traversed in a depth-first search, starting from Node.
> +  The input Node is skipped.
> +
> +  @param [in]       Fdt         Pointer to a Flattened Device Tree.
> +  @param [in]       FdtBranch   Only search in the sub-nodes of this branch.
> +                                Write (-1) to search the whole tree.
> +  @param [in]       NodeName    The node name to search.
> +                                This is a NULL terminated string.
> +  @param [in, out]  Node        At entry: Node offset to start the search.
> +                                          This first node is skipped.
> +                                          Write (-1) to search the whole tree.
> +                                At exit:  If success, contains the offset of
> +                                          the next node in the branch
> +                                          having a matching name.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_ABORTED             An error occurred.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_NOT_FOUND           No matching node found.
> +**/
> +EFI_STATUS
> +EFIAPI
> +FdtGetNextNamedNodeInBranch (
> +  IN      CONST VOID    * Fdt,
> +  IN            INT32     FdtBranch,
> +  IN      CONST CHAR8   * NodeName,
> +  IN OUT        INT32   * Node
> +  )
> +{
> +  return FdtGetNextCondNodeInBranch (
> +           Fdt,
> +           FdtBranch,
> +           FdtNodeHasName,
> +           NodeName,
> +           Node
> +           );
> +}
> +
> +/** Get the next node in a branch with at least one compatible property.
> +
> +  The Device tree is traversed in a depth-first search, starting from Node.
> +  The input Node is skipped.
> +
> +  @param [in]       Fdt         Pointer to a Flattened Device Tree.
> +  @param [in]       FdtBranch   Only search in the sub-nodes of this branch.
> +                                Write (-1) to search the whole tree.
> +  @param [in]  CompatNamesInfo  Table of compatible strings to compare with
> +                                the compatible property of the node.
> +  @param [in, out]  Node        At entry: Node offset to start the search.
> +                                          This first node is skipped.
> +                                          Write (-1) to search the whole tree.
> +                                At exit:  If success, contains the offset of
> +                                          the next node in the branch
> +                                          being compatible.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_ABORTED             An error occurred.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_NOT_FOUND           No matching node found.
> +**/
> +EFI_STATUS
> +EFIAPI
> +FdtGetNextCompatNodeInBranch (
> +  IN      CONST VOID                * Fdt,
> +  IN            INT32                 FdtBranch,
> +  IN      CONST COMPATIBILITY_INFO  * CompatNamesInfo,
> +  IN OUT        INT32               * Node
> +  )
> +{
> +  return FdtGetNextCondNodeInBranch (
> +           Fdt,
> +           FdtBranch,
> +           FdtNodeIsCompatible,
> +           (CONST VOID*)CompatNamesInfo,
> +           Node
> +           );
> +}
> +
> +/** Get the next node in a branch having the PropName property.
> +
> +  The Device tree is traversed in a depth-first search, starting from Node.
> +  The input Node is skipped.
> +
> +  @param [in]       Fdt         Pointer to a Flattened Device Tree.
> +  @param [in]       FdtBranch   Only search in the sub-nodes of this branch.
> +                                Write (-1) to search the whole tree.
> +  @param [in]       PropName    Name of the property to search.
> +                                This is a NULL terminated string.
> +  @param [in, out]  Node        At entry: Node offset to start the search.
> +                                          This first node is skipped.
> +                                          Write (-1) to search the whole tree.
> +                                At exit:  If success, contains the offset of
> +                                          the next node in the branch
> +                                          being compatible.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_ABORTED             An error occurred.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_NOT_FOUND           No matching node found.
> +**/
> +EFI_STATUS
> +EFIAPI
> +FdtGetNextPropNodeInBranch (
> +  IN      CONST VOID    * Fdt,
> +  IN            INT32     FdtBranch,
> +  IN      CONST CHAR8   * PropName,
> +  IN OUT        INT32   * Node
> +  )
> +{
> +  return FdtGetNextCondNodeInBranch (
> +           Fdt,
> +           FdtBranch,
> +           FdtNodeHasProperty,
> +           (CONST VOID*)PropName,
> +           Node
> +           );
> +}
> +
> +/** Count the number of Device Tree nodes fulfilling a condition
> +    in a Device Tree branch.
> +
> +  The condition to fulfill is checked by the NodeChecker function.
> +  Context is passed to NodeChecker.
> +
> +  @param [in]  Fdt              Pointer to a Flattened Device Tree.
> +  @param [in]  FdtBranch        Only search in the sub-nodes of this branch.
> +                                Write (-1) to search the whole tree.
> +  @param [in]  NodeChecker      Function called to check the condition is
> +                                fulfilled.
> +  @param [in]  Context          Context for the NodeChecker.
> +  @param [out] NodeCount        If success, contains the count of nodes
> +                                fulfilling the condition.
> +                                Can be 0.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_ABORTED             An error occurred.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +FdtCountCondNodeInBranch (
> +  IN  CONST VOID              * Fdt,
> +  IN        INT32               FdtBranch,
> +  IN        NODE_CHECKER_FUNC   NodeChecker,
> +  IN  CONST VOID              * Context,
> +  OUT       UINT32            * NodeCount
> +  )
> +{
> +  EFI_STATUS    Status;
> +  INT32         CurrNode;
> +
> +  if ((Fdt == NULL)         ||
> +      (NodeChecker == NULL) ||
> +      (NodeCount == NULL)) {
> +    ASSERT (0);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  *NodeCount = 0;
> +  CurrNode = FdtBranch;
> +  while (TRUE) {
> +    Status = FdtGetNextCondNodeInBranch (
> +               Fdt,
> +               FdtBranch,
> +               NodeChecker,
> +               Context,
> +               &CurrNode
> +               );
> +    if (EFI_ERROR (Status)  &&
> +        (Status != EFI_NOT_FOUND)) {
> +      ASSERT (0);
> +      return Status;
> +    } else if (Status == EFI_NOT_FOUND) {
> +      break;
> +    }
> +    (*NodeCount)++;
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/** Count the number of nodes in a branch with the input name.
> +
> +  @param [in]  Fdt              Pointer to a Flattened Device Tree.
> +  @param [in]  FdtBranch        Only search in the sub-nodes of this branch.
> +                                Write (-1) to search the whole tree.
> +  @param [in]  NodeName         Node name to search.
> +                                This is a NULL terminated string.
> +  @param [out] NodeCount        If success, contains the count of nodes
> +                                fulfilling the condition.
> +                                Can be 0.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_ABORTED             An error occurred.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +**/
> +EFI_STATUS
> +EFIAPI
> +FdtCountNamedNodeInBranch (
> +  IN  CONST VOID    * Fdt,
> +  IN        INT32     FdtBranch,
> +  IN  CONST CHAR8   * NodeName,
> +  OUT       UINT32  * NodeCount
> +  )
> +{
> +  return FdtCountCondNodeInBranch (
> +           Fdt,
> +           FdtBranch,
> +           FdtNodeHasName,
> +           NodeName,
> +           NodeCount
> +           );
> +}
> +
> +/** Count the number of nodes in a branch with at least
> +    one compatible property.
> +
> +  @param [in]  Fdt              Pointer to a Flattened Device Tree.
> +  @param [in]  FdtBranch        Only search in the sub-nodes of this branch.
> +                                Write (-1) to search the whole tree.
> +  @param [in]  CompatNamesInfo  Table of compatible strings to
> +                                compare with the compatible property
> +                                of the node.
> +  @param [out] NodeCount        If success, contains the count of nodes
> +                                fulfilling the condition.
> +                                Can be 0.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_ABORTED             An error occurred.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +**/
> +EFI_STATUS
> +EFIAPI
> +FdtCountCompatNodeInBranch (
> +  IN  CONST VOID                * Fdt,
> +  IN        INT32                 FdtBranch,
> +  IN  CONST COMPATIBILITY_INFO  * CompatNamesInfo,
> +  OUT       UINT32              * NodeCount
> +  )
> +{
> +  return FdtCountCondNodeInBranch (
> +           Fdt,
> +           FdtBranch,
> +           FdtNodeIsCompatible,
> +           CompatNamesInfo,
> +           NodeCount
> +           );
> +}
> +
> +/** Count the number of nodes in a branch having the PropName property.
> +
> +  @param [in]  Fdt              Pointer to a Flattened Device Tree.
> +  @param [in]  FdtBranch        Only search in the sub-nodes of this branch.
> +                                Write (-1) to search the whole tree.
> +  @param [in]  PropName         Name of the property to search.
> +                                This is a NULL terminated string.
> +  @param [out] NodeCount        If success, contains the count of nodes
> +                                fulfilling the condition.
> +                                Can be 0.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_ABORTED             An error occurred.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +**/
> +EFI_STATUS
> +EFIAPI
> +FdtCountPropNodeInBranch (
> +  IN  CONST VOID      * Fdt,
> +  IN        INT32       FdtBranch,
> +  IN  CONST CHAR8     * PropName,
> +  OUT       UINT32    * NodeCount
> +  )
> +{
> +  return FdtCountCondNodeInBranch (
> +           Fdt,
> +           FdtBranch,
> +           FdtNodeHasProperty,
> +           PropName,
> +           NodeCount
> +           );
> +}
> +
> +/** Get the interrupt-controller node handling the interrupts of
> +    the input node.
> +
> +  To do this, recursively search a node with either the "interrupt-controller"
> +  or the "interrupt-parent" property in the parents of Node.
> +
> +  Devicetree Specification, Release v0.3,
> +  2.4.1 "Properties for Interrupt Generating Devices":
> +    Because the hierarchy of the nodes in the interrupt tree
> +    might not match the devicetree, the interrupt-parent
> +    property is available to make the definition of an
> +    interrupt parent explicit. The value is the phandle to the
> +    interrupt parent. If this property is missing from a
> +    device, its interrupt parent is assumed to be its devicetree
> +    parent.
> +
> +  @param [in]  Fdt              Pointer to a Flattened Device Tree.
> +  @param [in]  Node             Offset of the node to start the search.
> +  @param [out] IntcNode         If success, contains the offset of the
> +                                interrupt-controller node.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_NOT_FOUND           No interrupt-controller node found.
> +  @retval EFI_ABORTED             An error occurred.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +**/
> +EFI_STATUS
> +EFIAPI
> +FdtGetIntcParentNode (
> +  IN  CONST VOID    * Fdt,
> +  IN        INT32     Node,
> +  OUT       INT32   * IntcNode
> +  )
> +{
> +  CONST UINT32  * PHandle;
> +  INT32           Size;
> +  CONST VOID    * Prop;
> +
> +  if ((Fdt == NULL) ||
> +      (IntcNode == NULL)) {
> +    ASSERT (0);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  while (TRUE) {
> +    // Check whether the node has the "interrupt-controller" property.
> +    Prop = fdt_getprop (Fdt, Node, "interrupt-controller", &Size);
> +    if ((Prop != NULL) && (Size >= 0)) {
> +      // The interrupt-controller has been found.
> +      *IntcNode = Node;
> +      return EFI_SUCCESS;
> +    } else {
> +      // Check whether the node has the "interrupt-parent" property.
> +      PHandle = fdt_getprop (Fdt, Node, "interrupt-parent", &Size);
> +      if ((PHandle != NULL) && (Size == sizeof (UINT32))) {
> +        // The phandle of the interrupt-controller has been found.
> +        // Search the node having this phandle and return it.
> +        Node = fdt_node_offset_by_phandle (Fdt, fdt32_to_cpu (*PHandle));
> +        if (Node < 0) {
> +          ASSERT (0);
> +          return EFI_ABORTED;
> +        }
> +
> +        *IntcNode = Node;
> +        return EFI_SUCCESS;
> +      } else if (Size != -FDT_ERR_NOTFOUND) {
> +        ASSERT (0);
> +        return EFI_ABORTED;
> +      }
> +    }
> +
> +    if (Node == 0) {
> +      // We are at the root of the tree. Not parent available.
> +      return EFI_NOT_FOUND;
> +    }
> +
> +    // Get the parent of the node.
> +    Node = fdt_parent_offset (Fdt, Node);
> +    if (Node < 0) {
> +      // An error occurred.
> +      ASSERT (0);
> +      return EFI_ABORTED;
> +    }
> +  } // while
> +}
> +
> +/** Get the "interrupt-cells" property value of the node.
> +
> +  The "interrupts" property requires to know the number of cells used
> +  to encode an interrupt. This information is stored in the
> +  interrupt-controller of the input Node.
> +
> +  @param [in]  Fdt          Pointer to a Flattened Device Tree (Fdt).
> +  @param [in]  IntcNode     Offset of an interrupt-controller node.
> +  @param [out] IntCells     If success, contains the "interrupt-cells"
> +                            property of the IntcNode.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_UNSUPPORTED         Unsupported.
> +**/
> +EFI_STATUS
> +EFIAPI
> +FdtGetInterruptCellsInfo (
> +  IN  CONST VOID      * Fdt,
> +  IN        INT32       IntcNode,
> +  OUT       INT32     * IntCells
> +  )
> +{
> +  CONST UINT32  * Data;
> +  INT32           Size;
> +
> +  if ((Fdt == NULL) ||
> +      (IntCells == NULL)) {
> +    ASSERT (0);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Data = fdt_getprop (Fdt, IntcNode, "#interrupt-cells", &Size);
> +  if ((Data == NULL) || (Size != sizeof (UINT32))) {
> +    // If error or not on one UINT32 cell.
> +    ASSERT (0);
> +    return EFI_ABORTED;
> +  }
> +
> +  *IntCells = fdt32_to_cpu (*Data);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** Get the "#address-cells" and/or "#size-cells" property of the node.
> +
> +  According to the Device Tree specification, s2.3.5 "#address-cells and
> +  #size-cells":
> +  "If missing, a client program should assume a default value of 2 for
> +  #address-cells, and a value of 1 for #size-cells."
> +
> +  @param [in]  Fdt              Pointer to a Flattened Device Tree.
> +  @param [in]  Node             Offset of the node having to get the
> +                                "#address-cells" and "#size-cells"
> +                                properties from.
> +  @param [out] AddressCells     If success, number of address-cells.
> +                                If the property is not available,
> +                                default value is 2.
> +  @param [out] SizeCells        If success, number of size-cells.
> +                                If the property is not available,
> +                                default value is 1.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_ABORTED             An error occurred.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +**/
> +EFI_STATUS
> +EFIAPI
> +FdtGetAddressInfo (
> +  IN  CONST VOID      * Fdt,
> +  IN        INT32       Node,
> +  OUT       INT32     * AddressCells,   OPTIONAL
> +  OUT       INT32     * SizeCells       OPTIONAL
> +  )
> +{
> +  if (Fdt == NULL) {
> +    ASSERT (0);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (AddressCells != NULL) {
> +    *AddressCells = fdt_address_cells (Fdt, Node);
> +    if (*AddressCells < 0) {
> +      ASSERT (0);
> +      return EFI_ABORTED;
> +    }
> +  }
> +
> +  if (SizeCells != NULL) {
> +    *SizeCells = fdt_size_cells (Fdt, Node);
> +    if (*SizeCells < 0) {
> +      ASSERT (0);
> +      return EFI_ABORTED;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** Get the "#address-cells" and/or "#size-cells" property of the parent node.
> +
> +  According to the Device Tree specification, s2.3.5 "#address-cells and
> +  #size-cells":
> +  "If missing, a client program should assume a default value of 2 for
> +  #address-cells, and a value of 1 for #size-cells."
> +
> +  @param [in]  Fdt              Pointer to a Flattened Device Tree.
> +  @param [in]  Node             Offset of the node having to get the
> +                                "#address-cells" and "#size-cells"
> +                                properties from its parent.
> +  @param [out] AddressCells     If success, number of address-cells.
> +                                If the property is not available,
> +                                default value is 2.
> +  @param [out] SizeCells        If success, number of size-cells.
> +                                If the property is not available,
> +                                default value is 1.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_ABORTED             An error occurred.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +**/
> +EFI_STATUS
> +EFIAPI
> +FdtGetParentAddressInfo (
> +  IN  CONST VOID      * Fdt,
> +  IN        INT32       Node,
> +  OUT       INT32     * AddressCells,   OPTIONAL
> +  OUT       INT32     * SizeCells       OPTIONAL
> +  )
> +{
> +  if (Fdt == NULL) {
> +    ASSERT (0);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Node = fdt_parent_offset (Fdt, Node);
> +  if (Node < 0) {
> +    // End of the tree, or an error occurred.
> +    ASSERT (0);
> +    return EFI_ABORTED;
> +  }
> +
> +  return FdtGetAddressInfo (Fdt, Node, AddressCells, SizeCells);
> +}
> diff --git a/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.h b/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.h
> new file mode 100644
> index 000000000000..0076c5066d4c
> --- /dev/null
> +++ b/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.h
> @@ -0,0 +1,458 @@
> +/** @file
> +  Flattened device tree utility.
> +
> +  Copyright (c) 2021, ARM Limited. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +  @par Reference(s):
> +  - Device tree Specification - Release v0.3
> +  - linux/Documentation/devicetree/bindings/interrupt-controller/arm%2Cgic.yaml
> +  - linux//Documentation/devicetree/bindings/interrupt-controller/arm%2Cgic.yaml
> +**/
> +
> +#ifndef FDT_UTILITY_H_
> +#define FDT_UTILITY_H_
> +
> +/** Get the offset of an address in a "reg" Device Tree property.
> +
> +  In a Device Tree, the "reg" property stores address/size couples.
> +  They are stored on N 32-bits cells.
> +  Based on the value of the #address-cells, the #size-cells and the
> +  index in the "reg" property, compute the number of 32-bits cells
> +  to skip.
> +
> +  @param [in]  Index        Index in the reg property.
> +  @param [in]  AddrCells    Number of cells used to store an address.
> +  @param [in]  SizeCells    Number of cells used to store the size of
> +                            an address.
> +
> +  @retval  Number of 32-bits cells to skip to access the address.
> +*/
> +#define GET_DT_REG_ADDRESS_OFFSET(Index, AddrCells, SizeCells) (            \
> +          (Index) * ((AddrCells) + (SizeCells))                             \
> +          )
> +
> +/** Get the offset of an address size in a "reg" Device Tree property.
> +
> +  In a Device Tree, the "reg" property stores address/size couples.
> +  They are stored on N 32-bits cells.
> +  Based on the value of the #address-cells, the #size-cells and the
> +  index in the "reg" property, compute the number of 32-bits cells
> +  to skip.
> +
> +  @param [in]  Index        Index in the reg property.
> +  @param [in]  AddrCells    Number of cells used to store an address.
> +  @param [in]  SizeCells    Number of cells used to store the size of
> +                            an address.
> +
> +  @retval  Number of 32-bits cells to skip to access the address size.
> +*/
> +#define GET_DT_REG_SIZE_OFFSET(Index, AddrCells, SizeCells)  (              \
> +          GET_DT_REG_ADDRESS_OFFSET ((Index), (AddrCells), (SizeCells)) +   \
> +          (SizeCells)                                                       \
> +          )
> +
> +/// Maximum string length for compatible names.
> +#define COMPATIBLE_STR_LEN             (32U)
> +
> +/// Interrupt macros
> +#define PPI_OFFSET                     (16U)
> +#define SPI_OFFSET                     (32U)
> +#define DT_PPI_IRQ                     (1U)
> +#define DT_SPI_IRQ                     (0U)
> +#define DT_IRQ_IS_EDGE_TRIGGERED(x)    ((((x) & (BIT0 | BIT2)) != 0))
> +#define DT_IRQ_IS_ACTIVE_LOW(x)        ((((x) & (BIT1 | BIT3)) != 0))
> +#define IRQ_TYPE_OFFSET                (0U)
> +#define IRQ_NUMBER_OFFSET              (1U)
> +#define IRQ_FLAGS_OFFSET               (2U)
> +
> +/** Get the interrupt Id of an interrupt described in a fdt.
> +
> +  Data must describe a GIC interrupt. A GIC interrupt is on at least
> +  3 UINT32 cells.
> +  This function DOES NOT SUPPORT extended SPI range and extended PPI range.
> +
> +  @param [in]  Data   Pointer to the first cell of an "interrupts" property.
> +
> +  @retval  The interrupt id.
> +**/
> +UINT32
> +EFIAPI
> +FdtGetInterruptId (
> +  UINT32 CONST  * Data
> +  );
> +
> +/** Get the ACPI interrupt flags of an interrupt described in a fdt.
> +
> +  Data must describe a GIC interrupt. A GIC interrupt is on at least
> +  3 UINT32 cells.
> +
> +  @param [in]  Data   Pointer to the first cell of an "interrupts" property.
> +
> +  @retval  The interrupt flags (for ACPI).
> +**/
> +UINT32
> +EFIAPI
> +FdtGetInterruptFlags (
> +  UINT32 CONST  * Data
> +  );
> +
> +/** A structure describing a compatibility string.
> +*/
> +typedef struct CompatStr {
> +  CONST CHAR8 CompatStr[COMPATIBLE_STR_LEN];
> +} COMPATIBILITY_STR;
> +
> +/** Structure containing a list of compatible names and their count.
> +*/
> +typedef struct CompatibilityInfo {
> +  /// Count of entries in the NAME_TABLE.
> +  UINT32                     Count;
> +
> +  /// Pointer to a table storing the names.
> +  CONST COMPATIBILITY_STR  * CompatTable;
> +} COMPATIBILITY_INFO;
> +
> +/** Operate a check on a Device Tree node.
> +
> +  @param [in]  Fdt          Pointer to a Flattened Device Tree.
> +  @param [in]  NodeOffset   Offset of the node to compare input string.
> +  @param [in]  Context      Context to operate the check on the node.
> +
> +  @retval True    The check is correct.
> +  @retval FALSE   Otherwise, or error.
> +**/
> +typedef
> +BOOLEAN
> +(EFIAPI *NODE_CHECKER_FUNC) (
> +  IN  CONST VOID    * Fdt,
> +  IN        INT32     NodeOffset,
> +  IN  CONST VOID    * Context
> +  );
> +
> +/** Iterate through the list of strings in the Context,
> +    and check whether at least one string is matching the
> +    "compatible" property of the node.
> +
> +  @param [in]  Fdt          Pointer to a Flattened Device Tree.
> +  @param [in]  Node         Offset of the node to operate the check on.
> +  @param [in]  CompatInfo   COMPATIBILITY_INFO containing the list of compatible
> +                            strings to compare with the "compatible" property
> +                            of the node.
> +
> +  @retval TRUE    At least one string matched, the node is compatible.
> +  @retval FALSE   Otherwise, or error.
> +**/
> +BOOLEAN
> +EFIAPI
> +FdtNodeIsCompatible (
> +  IN  CONST VOID                * Fdt,
> +  IN        INT32                 Node,
> +  IN  CONST VOID                * CompatInfo
> +  );
> +
> +/** Check whether a node has a property.
> +
> +  @param [in]  Fdt          Pointer to a Flattened Device Tree.
> +  @param [in]  Node         Offset of the node to operate the check on.
> +  @param [in]  PropertyName Name of the property to search.
> +                            This is a NULL terminated string.
> +
> +  @retval True    The node has the property.
> +  @retval FALSE   Otherwise, or error.
> +**/
> +BOOLEAN
> +EFIAPI
> +FdtNodeHasProperty (
> +  IN  CONST VOID  * Fdt,
> +  IN        INT32   Node,
> +  IN  CONST VOID * PropertyName
> +  );
> +
> +/** Get the next node in a branch having a matching name.
> +
> +  The Device tree is traversed in a depth-first search, starting from Node.
> +  The input Node is skipped.
> +
> +  @param [in]       Fdt         Pointer to a Flattened Device Tree.
> +  @param [in]       FdtBranch   Only search in the sub-nodes of this branch.
> +                                Write (-1) to search the whole tree.
> +  @param [in]       NodeName    The node name to search.
> +                                This is a NULL terminated string.
> +  @param [in, out]  Node        At entry: Node offset to start the search.
> +                                          This first node is skipped.
> +                                          Write (-1) to search the whole tree.
> +                                At exit:  If success, contains the offset of
> +                                          the next node in the branch
> +                                          having a matching name.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_ABORTED             An error occurred.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_NOT_FOUND           No matching node found.
> +**/
> +EFI_STATUS
> +EFIAPI
> +FdtGetNextNamedNodeInBranch (
> +  IN      CONST VOID    * Fdt,
> +  IN            INT32     FdtBranch,
> +  IN      CONST CHAR8   * NodeName,
> +  IN OUT        INT32   * Node
> +  );
> +
> +/** Get the next node in a branch with at least one compatible property.
> +
> +  The Device tree is traversed in a depth-first search, starting from Node.
> +  The input Node is skipped.
> +
> +  @param [in]       Fdt         Pointer to a Flattened Device Tree.
> +  @param [in]       FdtBranch   Only search in the sub-nodes of this branch.
> +                                Write (-1) to search the whole tree.
> +  @param [in]  CompatNamesInfo  Table of compatible strings to compare with
> +                                the compatible property of the node.
> +  @param [in, out]  Node        At entry: Node offset to start the search.
> +                                          This first node is skipped.
> +                                          Write (-1) to search the whole tree.
> +                                At exit:  If success, contains the offset of
> +                                          the next node in the branch
> +                                          being compatible.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_ABORTED             An error occurred.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_NOT_FOUND           No matching node found.
> +**/
> +EFI_STATUS
> +EFIAPI
> +FdtGetNextCompatNodeInBranch (
> +  IN      CONST VOID                * Fdt,
> +  IN            INT32                 FdtBranch,
> +  IN      CONST COMPATIBILITY_INFO  * CompatNamesInfo,
> +  IN OUT        INT32               * Node
> +  );
> +
> +/** Get the next node in a branch having the PropName property.
> +
> +  The Device tree is traversed in a depth-first search, starting from Node.
> +  The input Node is skipped.
> +
> +  @param [in]       Fdt         Pointer to a Flattened Device Tree.
> +  @param [in]       FdtBranch   Only search in the sub-nodes of this branch.
> +                                Write (-1) to search the whole tree.
> +  @param [in]       PropName    Name of the property to search.
> +                                This is a NULL terminated string.
> +  @param [in, out]  Node        At entry: Node offset to start the search.
> +                                          This first node is skipped.
> +                                          Write (-1) to search the whole tree.
> +                                At exit:  If success, contains the offset of
> +                                          the next node in the branch
> +                                          being compatible.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_ABORTED             An error occurred.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_NOT_FOUND           No matching node found.
> +**/
> +EFI_STATUS
> +EFIAPI
> +FdtGetNextPropNodeInBranch (
> +  IN      CONST VOID    * Fdt,
> +  IN            INT32     FdtBranch,
> +  IN      CONST CHAR8   * PropName,
> +  IN OUT        INT32   * Node
> +  );
> +
> +/** Count the number of nodes in a branch with the input name.
> +
> +  @param [in]  Fdt              Pointer to a Flattened Device Tree.
> +  @param [in]  FdtBranch        Only search in the sub-nodes of this branch.
> +                                Write (-1) to search the whole tree.
> +  @param [in]  NodeName         Node name to search.
> +                                This is a NULL terminated string.
> +  @param [out] NodeCount        If success, contains the count of nodes
> +                                fulfilling the condition.
> +                                Can be 0.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_ABORTED             An error occurred.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +**/
> +EFI_STATUS
> +EFIAPI
> +FdtCountNamedNodeInBranch (
> +  IN  CONST VOID    * Fdt,
> +  IN        INT32     FdtBranch,
> +  IN  CONST CHAR8   * NodeName,
> +  OUT       UINT32  * NodeCount
> +  );
> +
> +/** Count the number of nodes in a branch with at least
> +    one compatible property.
> +
> +  @param [in]  Fdt              Pointer to a Flattened Device Tree.
> +  @param [in]  FdtBranch        Only search in the sub-nodes of this branch.
> +                                Write (-1) to search the whole tree.
> +  @param [in]  CompatibleTable  Table of compatible strings to
> +                                compare with the compatible property
> +                                of the node.
> +  @param [out] NodeCount        If success, contains the count of nodes
> +                                fulfilling the condition.
> +                                Can be 0.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_ABORTED             An error occurred.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +**/
> +EFI_STATUS
> +EFIAPI
> +FdtCountCompatNodeInBranch (
> +  IN  CONST VOID                * Fdt,
> +  IN        INT32                 FdtBranch,
> +  IN  CONST COMPATIBILITY_INFO  * CompatNamesInfo,
> +  OUT       UINT32              * NodeCount
> +  );
> +
> +/** Count the number of nodes in a branch having the PropName property.
> +
> +  @param [in]  Fdt              Pointer to a Flattened Device Tree.
> +  @param [in]  FdtBranch        Only search in the sub-nodes of this branch.
> +                                Write (-1) to search the whole tree.
> +  @param [in]  PropName         Name of the property to search.
> +                                This is a NULL terminated string.
> +  @param [out] NodeCount        If success, contains the count of nodes
> +                                fulfilling the condition.
> +                                Can be 0.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_ABORTED             An error occurred.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +**/
> +EFI_STATUS
> +EFIAPI
> +FdtCountPropNodeInBranch (
> +  IN  CONST VOID      * Fdt,
> +  IN        INT32       FdtBranch,
> +  IN  CONST CHAR8     * PropName,
> +  OUT       UINT32    * NodeCount
> +  );
> +
> +/** Get the interrupt-controller node handling the interrupts of
> +    the input node.
> +
> +  To do this, recursively search a node with either the "interrupt-controller"
> +  or the "interrupt-parent" property in the parents of Node.
> +
> +  Devicetree Specification, Release v0.3,
> +  2.4.1 "Properties for Interrupt Generating Devices":
> +    Because the hierarchy of the nodes in the interrupt tree
> +    might not match the devicetree, the interrupt-parent
> +    property is available to make the definition of an
> +    interrupt parent explicit. The value is the phandle to the
> +    interrupt parent. If this property is missing from a
> +    device, its interrupt parent is assumed to be its devicetree
> +    parent.
> +
> +  @param [in]  Fdt              Pointer to a Flattened Device Tree.
> +  @param [in]  Node             Offset of the node to start the search.
> +  @param [out] IntcNode         If success, contains the offset of the
> +                                interrupt-controller node.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_NOT_FOUND           No interrupt-controller node found.
> +  @retval EFI_ABORTED             An error occurred.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +**/
> +EFI_STATUS
> +EFIAPI
> +FdtGetIntcParentNode (
> +  IN  CONST VOID    * Fdt,
> +  IN        INT32     Node,
> +  OUT       INT32   * IntcNode
> +  );
> +
> +/** Get the "interrupt-cells" property value of the node.
> +
> +  The "interrupts" property requires to know the number of cells used
> +  to encode an interrupt. This information is stored in the
> +  interrupt-controller of the input Node.
> +
> +  @param [in]  Fdt          Pointer to a Flattened Device Tree (Fdt).
> +  @param [in]  IntcNode     Offset of an interrupt-controller node.
> +  @param [out] IntCells     If success, contains the "interrupt-cells"
> +                            property of the IntcNode.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +  @retval EFI_UNSUPPORTED         Unsupported.
> +**/
> +EFI_STATUS
> +EFIAPI
> +FdtGetInterruptCellsInfo (
> +  IN  CONST VOID      * Fdt,
> +  IN        INT32       IntcNode,
> +  OUT       INT32     * InterruptCells
> +  );
> +
> +/** Get the "#address-cells" and/or "#size-cells" property of the node.
> +
> +  According to the Device Tree specification, s2.3.5 "#address-cells and
> +  #size-cells":
> +  "If missing, a client program should assume a default value of 2 for
> +  #address-cells, and a value of 1 for #size-cells."
> +
> +  @param [in]  Fdt              Pointer to a Flattened Device Tree.
> +  @param [in]  Node             Offset of the node having to get the
> +                                "#address-cells" and "#size-cells"
> +                                properties from.
> +  @param [out] AddressCells     If success, number of address-cells.
> +                                If the property is not available,
> +                                default value is 2.
> +  @param [out] SizeCells        If success, number of size-cells.
> +                                If the property is not available,
> +                                default value is 1.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_ABORTED             An error occurred.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +**/
> +EFI_STATUS
> +EFIAPI
> +FdtGetAddressInfo (
> +  IN  CONST VOID      * Fdt,
> +  IN        INT32       Node,
> +  OUT       INT32     * AddressCells,   OPTIONAL
> +  OUT       INT32     * SizeCells       OPTIONAL
> +  );
> +
> +/** Get the "#address-cells" and/or "#size-cells" property of the parent node.
> +
> +  According to the Device Tree specification, s2.3.5 "#address-cells and
> +  #size-cells":
> +  "If missing, a client program should assume a default value of 2 for
> +  #address-cells, and a value of 1 for #size-cells."
> +
> +  @param [in]  Fdt              Pointer to a Flattened Device Tree.
> +  @param [in]  Node             Offset of the node having to get the
> +                                "#address-cells" and "#size-cells"
> +                                properties from its parent.
> +  @param [out] AddressCells     If success, number of address-cells.
> +                                If the property is not available,
> +                                default value is 2.
> +  @param [out] SizeCells        If success, number of size-cells.
> +                                If the property is not available,
> +                                default value is 1.
> +
> +  @retval EFI_SUCCESS             The function completed successfully.
> +  @retval EFI_ABORTED             An error occurred.
> +  @retval EFI_INVALID_PARAMETER   Invalid parameter.
> +**/
> +EFI_STATUS
> +EFIAPI
> +FdtGetParentAddressInfo (
> +  IN  CONST VOID      * Fdt,
> +  IN        INT32       Node,
> +  OUT       INT32     * AddressCells,   OPTIONAL
> +  OUT       INT32     * SizeCells       OPTIONAL
> +  );
> +
> +#endif // FDT_UTILITY_H_



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#83400): https://edk2.groups.io/g/devel/message/83400
Mute This Topic: https://groups.io/mt/83736624/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-