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