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