--- /dev/null
+/** @file\r
+ AML Tree Enumerator.\r
+\r
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+**/\r
+\r
+#include <AmlNodeDefines.h>\r
+\r
+#include <AmlCoreInterface.h>\r
+#include <Tree/AmlTree.h>\r
+\r
+/** Enumerate all nodes of the subtree under the input Node in the AML\r
+ bytestream order (i.e. in a depth first order), and call the CallBack\r
+ function with the input Context.\r
+ The prototype of the Callback function is EDKII_AML_TREE_ENUM_CALLBACK.\r
+\r
+ @param [in] Node Enumerate nodes of the subtree under this Node.\r
+ Must be a valid node.\r
+ @param [in] CallBack Callback function to call on each node.\r
+ @param [in, out] Context Void pointer used to pass some information\r
+ to the Callback function.\r
+ Optional, can be NULL.\r
+ @param [out] Status Optional parameter that can be used to get\r
+ the status of the Callback function.\r
+ If used, need to be init to EFI_SUCCESS.\r
+\r
+ @retval TRUE if the enumeration can continue or has finished without\r
+ interruption.\r
+ @retval FALSE if the enumeration needs to stopped or has stopped.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+AmlEnumTree (\r
+ IN AML_NODE_HEADER * Node,\r
+ IN EDKII_AML_TREE_ENUM_CALLBACK CallBack,\r
+ IN OUT VOID * Context, OPTIONAL\r
+ OUT EFI_STATUS * Status OPTIONAL\r
+ )\r
+{\r
+ BOOLEAN ContinueEnum;\r
+\r
+ EAML_PARSE_INDEX Index;\r
+ EAML_PARSE_INDEX MaxIndex;\r
+\r
+ LIST_ENTRY * StartLink;\r
+ LIST_ENTRY * CurrentLink;\r
+\r
+ if (!IS_AML_NODE_VALID (Node) || (CallBack == NULL)) {\r
+ ASSERT (0);\r
+ if (Status != NULL) {\r
+ *Status = EFI_INVALID_PARAMETER;\r
+ }\r
+ return FALSE;\r
+ }\r
+\r
+ ContinueEnum = (*CallBack)(Node, Context, Status);\r
+ if (ContinueEnum == FALSE) {\r
+ return ContinueEnum;\r
+ }\r
+\r
+ // Iterate through the fixed list of arguments.\r
+ MaxIndex = (EAML_PARSE_INDEX)AmlGetFixedArgumentCount (\r
+ (AML_OBJECT_NODE*)Node\r
+ );\r
+ for (Index = EAmlParseIndexTerm0; Index < MaxIndex; Index++) {\r
+ ContinueEnum = AmlEnumTree (\r
+ AmlGetFixedArgument ((AML_OBJECT_NODE*)Node, Index),\r
+ CallBack,\r
+ Context,\r
+ Status\r
+ );\r
+ if (ContinueEnum == FALSE) {\r
+ return ContinueEnum;\r
+ }\r
+ }\r
+\r
+ // Iterate through the variable list of arguments.\r
+ StartLink = AmlNodeGetVariableArgList (Node);\r
+ if (StartLink != NULL) {\r
+ CurrentLink = StartLink->ForwardLink;\r
+ while (CurrentLink != StartLink) {\r
+ ContinueEnum = AmlEnumTree (\r
+ (AML_NODE_HEADER*)CurrentLink,\r
+ CallBack,\r
+ Context,\r
+ Status\r
+ );\r
+ if (ContinueEnum == FALSE) {\r
+ return ContinueEnum;\r
+ }\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ } // while\r
+ }\r
+\r
+ return ContinueEnum;\r
+}\r