REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the DynamicTablesPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
		
			
				
	
	
		
			1064 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1064 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  AML Tree.
 | 
						|
 | 
						|
  Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
 | 
						|
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
**/
 | 
						|
 | 
						|
#include <Tree/AmlTree.h>
 | 
						|
 | 
						|
#include <AmlCoreInterface.h>
 | 
						|
#include <Tree/AmlNode.h>
 | 
						|
#include <Tree/AmlTreeTraversal.h>
 | 
						|
#include <Utils/AmlUtility.h>
 | 
						|
 | 
						|
/** Get the parent node of the input Node.
 | 
						|
 | 
						|
  @param [in] Node  Pointer to a node.
 | 
						|
 | 
						|
  @return The parent node of the input Node.
 | 
						|
          NULL otherwise.
 | 
						|
**/
 | 
						|
AML_NODE_HEADER *
 | 
						|
EFIAPI
 | 
						|
AmlGetParent (
 | 
						|
  IN  AML_NODE_HEADER  *Node
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (IS_AML_DATA_NODE (Node) ||
 | 
						|
      IS_AML_OBJECT_NODE (Node))
 | 
						|
  {
 | 
						|
    return Node->Parent;
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/** Get the root node from any node of the tree.
 | 
						|
    This is done by climbing up the tree until the root node is reached.
 | 
						|
 | 
						|
  @param  [in]  Node    Pointer to a node.
 | 
						|
 | 
						|
  @return The root node of the tree.
 | 
						|
          NULL if error.
 | 
						|
**/
 | 
						|
AML_ROOT_NODE *
 | 
						|
EFIAPI
 | 
						|
AmlGetRootNode (
 | 
						|
  IN  CONST AML_NODE_HEADER  *Node
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (!IS_AML_NODE_VALID (Node)) {
 | 
						|
    ASSERT (0);
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  while (!IS_AML_ROOT_NODE (Node)) {
 | 
						|
    Node = Node->Parent;
 | 
						|
    if (!IS_AML_NODE_VALID (Node)) {
 | 
						|
      ASSERT (0);
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return (AML_ROOT_NODE *)Node;
 | 
						|
}
 | 
						|
 | 
						|
/** Get the node at the input Index in the fixed argument list of the input
 | 
						|
    ObjectNode.
 | 
						|
 | 
						|
  @param  [in]  ObjectNode  Pointer to an object node.
 | 
						|
  @param  [in]  Index       The Index of the fixed argument to get.
 | 
						|
 | 
						|
  @return The node at the input Index in the fixed argument list
 | 
						|
          of the input ObjectNode.
 | 
						|
          NULL otherwise, e.g. if the node is not an object node, or no
 | 
						|
          node is available at this Index.
 | 
						|
**/
 | 
						|
AML_NODE_HEADER *
 | 
						|
EFIAPI
 | 
						|
AmlGetFixedArgument (
 | 
						|
  IN  AML_OBJECT_NODE   *ObjectNode,
 | 
						|
  IN  EAML_PARSE_INDEX  Index
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (IS_AML_OBJECT_NODE (ObjectNode)) {
 | 
						|
    if (Index < (EAML_PARSE_INDEX)AmlGetFixedArgumentCount (ObjectNode)) {
 | 
						|
      return ObjectNode->FixedArgs[Index];
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/** Check whether the input Node is in the fixed argument list of its parent
 | 
						|
    node.
 | 
						|
 | 
						|
  If so, IndexPtr contains this Index.
 | 
						|
 | 
						|
  @param  [in]  Node          Pointer to a Node.
 | 
						|
  @param  [out] IndexPtr      Pointer holding the Index of the Node in
 | 
						|
                              its parent's fixed argument list.
 | 
						|
 | 
						|
  @retval TRUE   The node is a fixed argument and the index
 | 
						|
                 in IndexPtr is valid.
 | 
						|
  @retval FALSE  The node is not a fixed argument.
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
EFIAPI
 | 
						|
AmlIsNodeFixedArgument (
 | 
						|
  IN  CONST  AML_NODE_HEADER   *Node,
 | 
						|
  OUT        EAML_PARSE_INDEX  *IndexPtr
 | 
						|
  )
 | 
						|
{
 | 
						|
  AML_NODE_HEADER  *ParentNode;
 | 
						|
 | 
						|
  EAML_PARSE_INDEX  Index;
 | 
						|
  EAML_PARSE_INDEX  MaxIndex;
 | 
						|
 | 
						|
  if ((IndexPtr == NULL)               ||
 | 
						|
      (!IS_AML_DATA_NODE (Node)        &&
 | 
						|
       !IS_AML_OBJECT_NODE (Node)))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  ParentNode = AmlGetParent ((AML_NODE_HEADER *)Node);
 | 
						|
  if (IS_AML_ROOT_NODE (ParentNode)) {
 | 
						|
    return FALSE;
 | 
						|
  } else if (IS_AML_DATA_NODE (ParentNode)) {
 | 
						|
    // Tree is inconsistent.
 | 
						|
    ASSERT (0);
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  // Check whether the Node is in the fixed argument list.
 | 
						|
  MaxIndex = (EAML_PARSE_INDEX)AmlGetFixedArgumentCount (
 | 
						|
                                 (AML_OBJECT_NODE *)ParentNode
 | 
						|
                                 );
 | 
						|
  for (Index = EAmlParseIndexTerm0; Index < MaxIndex; Index++) {
 | 
						|
    if (AmlGetFixedArgument ((AML_OBJECT_NODE *)ParentNode, Index) == Node) {
 | 
						|
      *IndexPtr = Index;
 | 
						|
      return TRUE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/** Set the fixed argument of the ObjectNode at the Index to the NewNode.
 | 
						|
 | 
						|
  It is the caller's responsibility to save the old node, if desired,
 | 
						|
  otherwise the reference to the old node will be lost.
 | 
						|
  If NewNode is not NULL, set its parent to ObjectNode.
 | 
						|
 | 
						|
  @param  [in]  ObjectNode    Pointer to an object node.
 | 
						|
  @param  [in]  Index         Index in the fixed argument list of
 | 
						|
                              the ObjectNode to set.
 | 
						|
  @param  [in]  NewNode       Pointer to the NewNode.
 | 
						|
                              Can be NULL, a data node or an object node.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The function completed successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AmlSetFixedArgument (
 | 
						|
  IN  AML_OBJECT_NODE   *ObjectNode,
 | 
						|
  IN  EAML_PARSE_INDEX  Index,
 | 
						|
  IN  AML_NODE_HEADER   *NewNode
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (IS_AML_OBJECT_NODE (ObjectNode)                                     &&
 | 
						|
      (Index <= (EAML_PARSE_INDEX)AmlGetFixedArgumentCount (ObjectNode))  &&
 | 
						|
      ((NewNode == NULL)                                                  ||
 | 
						|
       IS_AML_OBJECT_NODE (NewNode)                                       ||
 | 
						|
       IS_AML_DATA_NODE (NewNode)))
 | 
						|
  {
 | 
						|
    ObjectNode->FixedArgs[Index] = NewNode;
 | 
						|
 | 
						|
    // If NewNode is a data node or an object node, set its parent.
 | 
						|
    if (NewNode != NULL) {
 | 
						|
      NewNode->Parent = (AML_NODE_HEADER *)ObjectNode;
 | 
						|
    }
 | 
						|
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  ASSERT (0);
 | 
						|
  return EFI_INVALID_PARAMETER;
 | 
						|
}
 | 
						|
 | 
						|
/** If the given AML_NODE_HEADER has a variable list of arguments,
 | 
						|
    return a pointer to this list.
 | 
						|
    Return NULL otherwise.
 | 
						|
 | 
						|
  @param  [in]  Node  Pointer to the AML_NODE_HEADER to check.
 | 
						|
 | 
						|
  @return The list of variable arguments if there is one.
 | 
						|
          NULL otherwise.
 | 
						|
**/
 | 
						|
LIST_ENTRY *
 | 
						|
EFIAPI
 | 
						|
AmlNodeGetVariableArgList (
 | 
						|
  IN  CONST AML_NODE_HEADER  *Node
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (IS_AML_ROOT_NODE (Node)) {
 | 
						|
    return &(((AML_ROOT_NODE *)Node)->VariableArgs);
 | 
						|
  } else if (IS_AML_OBJECT_NODE (Node)) {
 | 
						|
    return &(((AML_OBJECT_NODE *)Node)->VariableArgs);
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/** Remove the Node from its parent's variable list of arguments.
 | 
						|
 | 
						|
  The function will fail if the Node is in its parent's fixed
 | 
						|
  argument list.
 | 
						|
  The Node is not deleted. The deletion is done separately
 | 
						|
  from the removal.
 | 
						|
 | 
						|
  @param  [in]  Node  Pointer to a Node.
 | 
						|
                      Must be a data node or an object node.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The function completed successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AmlRemoveNodeFromVarArgList (
 | 
						|
  IN  AML_NODE_HEADER  *Node
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS       Status;
 | 
						|
  AML_NODE_HEADER  *ParentNode;
 | 
						|
  UINT32           Size;
 | 
						|
 | 
						|
  if ((!IS_AML_DATA_NODE (Node) &&
 | 
						|
       !IS_AML_OBJECT_NODE (Node)))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  ParentNode = AmlGetParent (Node);
 | 
						|
  if (!IS_AML_ROOT_NODE (ParentNode)  &&
 | 
						|
      !IS_AML_OBJECT_NODE (ParentNode))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  // Check the node is in its parent variable list of arguments.
 | 
						|
  if (!IsNodeInList (
 | 
						|
         AmlNodeGetVariableArgList (ParentNode),
 | 
						|
         &Node->Link
 | 
						|
         ))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  // Unlink Node from the tree.
 | 
						|
  RemoveEntryList (&Node->Link);
 | 
						|
  InitializeListHead (&Node->Link);
 | 
						|
  Node->Parent = NULL;
 | 
						|
 | 
						|
  // Get the size of the node removed.
 | 
						|
  Status = AmlComputeSize (Node, &Size);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    ASSERT (0);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  // Propagate the information.
 | 
						|
  Status = AmlPropagateInformation (ParentNode, FALSE, Size, 1);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/** Detach the Node from the tree.
 | 
						|
 | 
						|
  The function will fail if the Node is in its parent's fixed
 | 
						|
  argument list.
 | 
						|
  The Node is not deleted. The deletion is done separately
 | 
						|
  from the removal.
 | 
						|
 | 
						|
  @param  [in]  Node  Pointer to a Node.
 | 
						|
                      Must be a data node or an object node.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The function completed successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AmlDetachNode (
 | 
						|
  IN  AML_NODE_HEADER  *Node
 | 
						|
  )
 | 
						|
{
 | 
						|
  return AmlRemoveNodeFromVarArgList (Node);
 | 
						|
}
 | 
						|
 | 
						|
/** Add the NewNode to the head of the variable list of arguments
 | 
						|
    of the ParentNode.
 | 
						|
 | 
						|
  @param  [in]  ParentNode  Pointer to the parent node.
 | 
						|
                            Must be a root or an object node.
 | 
						|
  @param  [in]  NewNode     Pointer to the node to add.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The function completed successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AmlVarListAddHead (
 | 
						|
  IN  AML_NODE_HEADER  *ParentNode,
 | 
						|
  IN  AML_NODE_HEADER  *NewNode
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  UINT32      NewSize;
 | 
						|
  LIST_ENTRY  *ChildrenList;
 | 
						|
 | 
						|
  // Check arguments and that NewNode is not already attached to a tree.
 | 
						|
  // ParentNode != Data Node AND NewNode != Root Node AND NewNode != attached.
 | 
						|
  if ((!IS_AML_ROOT_NODE (ParentNode)     &&
 | 
						|
       !IS_AML_OBJECT_NODE (ParentNode))  ||
 | 
						|
      (!IS_AML_DATA_NODE (NewNode)        &&
 | 
						|
       !IS_AML_OBJECT_NODE (NewNode))     ||
 | 
						|
      !AML_NODE_IS_DETACHED (NewNode))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  // Insert it at the head of the list.
 | 
						|
  ChildrenList = AmlNodeGetVariableArgList (ParentNode);
 | 
						|
  if (ChildrenList == NULL) {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  InsertHeadList (ChildrenList, &NewNode->Link);
 | 
						|
  NewNode->Parent = ParentNode;
 | 
						|
 | 
						|
  // Get the size of the NewNode.
 | 
						|
  Status = AmlComputeSize (NewNode, &NewSize);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    ASSERT (0);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  // Propagate the new information.
 | 
						|
  Status = AmlPropagateInformation (ParentNode, TRUE, NewSize, 1);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/** Add the NewNode to the tail of the variable list of arguments
 | 
						|
    of the ParentNode.
 | 
						|
 | 
						|
  NOTE: This is an internal function which does not propagate the size
 | 
						|
        when a new node is added.
 | 
						|
 | 
						|
  @param  [in]  ParentNode  Pointer to the parent node.
 | 
						|
                            Must be a root or an object node.
 | 
						|
  @param  [in]  NewNode     Pointer to the node to add.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The function completed successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AmlVarListAddTailInternal (
 | 
						|
  IN  AML_NODE_HEADER  *ParentNode,
 | 
						|
  IN  AML_NODE_HEADER  *NewNode
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY  *ChildrenList;
 | 
						|
 | 
						|
  // Check arguments and that NewNode is not already attached to a tree.
 | 
						|
  // ParentNode != Data Node AND NewNode != Root Node AND NewNode != attached.
 | 
						|
  if ((!IS_AML_ROOT_NODE (ParentNode)     &&
 | 
						|
       !IS_AML_OBJECT_NODE (ParentNode))  ||
 | 
						|
      (!IS_AML_DATA_NODE (NewNode)        &&
 | 
						|
       !IS_AML_OBJECT_NODE (NewNode))     ||
 | 
						|
      !AML_NODE_IS_DETACHED (NewNode))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  // Insert it at the tail of the list.
 | 
						|
  ChildrenList = AmlNodeGetVariableArgList (ParentNode);
 | 
						|
  if (ChildrenList == NULL) {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  InsertTailList (ChildrenList, &NewNode->Link);
 | 
						|
  NewNode->Parent = ParentNode;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/** Add the NewNode to the tail of the variable list of arguments
 | 
						|
    of the ParentNode.
 | 
						|
 | 
						|
  @param  [in]  ParentNode  Pointer to the parent node.
 | 
						|
                            Must be a root or an object node.
 | 
						|
  @param  [in]  NewNode     Pointer to the node to add.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The function completed successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AmlVarListAddTail (
 | 
						|
  IN  AML_NODE_HEADER  *ParentNode,
 | 
						|
  IN  AML_NODE_HEADER  *NewNode
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  UINT32      NewSize;
 | 
						|
 | 
						|
  // Add the NewNode and check arguments.
 | 
						|
  Status = AmlVarListAddTailInternal (ParentNode, NewNode);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    ASSERT (0);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  // Get the size of the NewNode.
 | 
						|
  Status = AmlComputeSize (NewNode, &NewSize);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    ASSERT (0);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  // Propagate the new information.
 | 
						|
  Status = AmlPropagateInformation (ParentNode, TRUE, NewSize, 1);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/** Add the NewNode before the Node in the list of variable
 | 
						|
    arguments of the Node's parent.
 | 
						|
 | 
						|
  @param  [in]  Node      Pointer to a node.
 | 
						|
                          Must be a root or an object node.
 | 
						|
  @param  [in]  NewNode   Pointer to the node to add.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The function completed successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AmlVarListAddBefore (
 | 
						|
  IN  AML_NODE_HEADER  *Node,
 | 
						|
  IN  AML_NODE_HEADER  *NewNode
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS       Status;
 | 
						|
  AML_NODE_HEADER  *ParentNode;
 | 
						|
  UINT32           NewSize;
 | 
						|
 | 
						|
  // Check arguments and that NewNode is not already attached to a tree.
 | 
						|
  if ((!IS_AML_DATA_NODE (NewNode)        &&
 | 
						|
       !IS_AML_OBJECT_NODE (NewNode))     ||
 | 
						|
      !AML_NODE_IS_DETACHED (NewNode))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  ParentNode = AmlGetParent (Node);
 | 
						|
  if (!IS_AML_ROOT_NODE (ParentNode)    &&
 | 
						|
      !IS_AML_OBJECT_NODE (ParentNode))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  // Insert it before the input Node.
 | 
						|
  InsertTailList (&Node->Link, &NewNode->Link);
 | 
						|
  NewNode->Parent = ParentNode;
 | 
						|
 | 
						|
  // Get the size of the NewNode.
 | 
						|
  Status = AmlComputeSize (NewNode, &NewSize);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    ASSERT (0);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  // Propagate the new information.
 | 
						|
  Status = AmlPropagateInformation (ParentNode, TRUE, NewSize, 1);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/** Add the NewNode after the Node in the variable list of arguments
 | 
						|
    of the Node's parent.
 | 
						|
 | 
						|
  @param  [in]  Node      Pointer to a node.
 | 
						|
                          Must be a root or an object node.
 | 
						|
  @param  [in]  NewNode   Pointer to the node to add.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The function completed successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AmlVarListAddAfter (
 | 
						|
  IN  AML_NODE_HEADER  *Node,
 | 
						|
  IN  AML_NODE_HEADER  *NewNode
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS       Status;
 | 
						|
  AML_NODE_HEADER  *ParentNode;
 | 
						|
  UINT32           NewSize;
 | 
						|
 | 
						|
  // Check arguments and that NewNode is not already attached to a tree.
 | 
						|
  if ((!IS_AML_DATA_NODE (NewNode)        &&
 | 
						|
       !IS_AML_OBJECT_NODE (NewNode))     ||
 | 
						|
      !AML_NODE_IS_DETACHED (NewNode))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  ParentNode = AmlGetParent (Node);
 | 
						|
  if (!IS_AML_ROOT_NODE (ParentNode)    &&
 | 
						|
      !IS_AML_OBJECT_NODE (ParentNode))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  // Insert the new node after the input Node.
 | 
						|
  InsertHeadList (&Node->Link, &NewNode->Link);
 | 
						|
  NewNode->Parent = ParentNode;
 | 
						|
 | 
						|
  // Get the size of the NewNode.
 | 
						|
  Status = AmlComputeSize (NewNode, &NewSize);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    ASSERT (0);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  // Propagate the new information.
 | 
						|
  Status = AmlPropagateInformation (ParentNode, TRUE, NewSize, 1);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/** Append a Resource Data node to the BufferOpNode.
 | 
						|
 | 
						|
  The Resource Data node is added at the end of the variable
 | 
						|
  list of arguments of the BufferOpNode, but before the End Tag.
 | 
						|
  If no End Tag is found, the function returns an error.
 | 
						|
 | 
						|
  @param  [in]  BufferOpNode  Buffer node containing resource data elements.
 | 
						|
  @param  [in]  NewRdNode     The new Resource Data node to add.
 | 
						|
 | 
						|
  @retval  EFI_SUCCESS            The function completed successfully.
 | 
						|
  @retval  EFI_INVALID_PARAMETER  Invalid parameter.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AmlAppendRdNode (
 | 
						|
  IN  AML_OBJECT_NODE  *BufferOpNode,
 | 
						|
  IN  AML_DATA_NODE    *NewRdNode
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS     Status;
 | 
						|
  AML_DATA_NODE  *LastRdNode;
 | 
						|
 | 
						|
  if (!AmlNodeCompareOpCode (BufferOpNode, AML_BUFFER_OP, 0)  ||
 | 
						|
      !IS_AML_DATA_NODE (NewRdNode)                           ||
 | 
						|
      (NewRdNode->DataType != EAmlNodeDataTypeResourceData))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  // To avoid re-computing checksums, if a new resource data elements is
 | 
						|
  // added/removed/modified in a list of resource data elements, the AmlLib
 | 
						|
  // resets the checksum to 0.
 | 
						|
  // It is possible to have only one Resource Data in a BufferOp with
 | 
						|
  // no EndTag, but it should not be possible to add a new Resource Data
 | 
						|
  // in the list in this case.
 | 
						|
  Status = AmlSetRdListCheckSum (BufferOpNode, 0);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    ASSERT (0);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  // Get the last Resource data node in the variable list of argument of the
 | 
						|
  // BufferOp node. This must be an EndTag, otherwise setting the checksum
 | 
						|
  // would have failed.
 | 
						|
  LastRdNode = (AML_DATA_NODE *)AmlGetPreviousVariableArgument (
 | 
						|
                                  (AML_NODE_HEADER *)BufferOpNode,
 | 
						|
                                  NULL
 | 
						|
                                  );
 | 
						|
  if ((LastRdNode == NULL)             ||
 | 
						|
      !IS_AML_DATA_NODE (LastRdNode)   ||
 | 
						|
      (LastRdNode->DataType != EAmlNodeDataTypeResourceData))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  // Add NewRdNode before the EndTag.
 | 
						|
  Status = AmlVarListAddBefore (
 | 
						|
             (AML_NODE_HEADER *)LastRdNode,
 | 
						|
             (AML_NODE_HEADER *)NewRdNode
 | 
						|
             )
 | 
						|
  ;
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/** Replace the fixed argument at the Index of the ParentNode with the NewNode.
 | 
						|
 | 
						|
  Note: This function unlinks the OldNode from the tree. It is the callers
 | 
						|
        responsibility to delete the OldNode if needed.
 | 
						|
 | 
						|
  @param  [in]  ParentNode  Pointer to the parent node.
 | 
						|
                            Must be an object node.
 | 
						|
  @param  [in]  Index       Index of the fixed argument to replace.
 | 
						|
  @param  [in]  NewNode     The new node to insert.
 | 
						|
                            Must be an object node or a data node.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The function completed successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AmlReplaceFixedArgument (
 | 
						|
  IN  AML_OBJECT_NODE   *ParentNode,
 | 
						|
  IN  EAML_PARSE_INDEX  Index,
 | 
						|
  IN  AML_NODE_HEADER   *NewNode
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  AML_NODE_HEADER   *OldNode;
 | 
						|
  UINT32            NewSize;
 | 
						|
  UINT32            OldSize;
 | 
						|
  AML_PARSE_FORMAT  FixedArgType;
 | 
						|
 | 
						|
  // Check arguments and that NewNode is not already attached to a tree.
 | 
						|
  if (!IS_AML_OBJECT_NODE (ParentNode)  ||
 | 
						|
      (!IS_AML_DATA_NODE (NewNode)      &&
 | 
						|
       !IS_AML_OBJECT_NODE (NewNode))   ||
 | 
						|
      !AML_NODE_IS_DETACHED (NewNode))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  // Perform some compatibility checks between NewNode and OldNode.
 | 
						|
  FixedArgType = ParentNode->AmlByteEncoding->Format[Index];
 | 
						|
  switch (FixedArgType) {
 | 
						|
    case EAmlFieldPkgLen:
 | 
						|
    {
 | 
						|
      // A FieldPkgLen can only have a parent node with the
 | 
						|
      // AML_IS_FIELD_ELEMENT flag.
 | 
						|
      if (!AmlNodeHasAttribute (
 | 
						|
             (AML_OBJECT_NODE *)ParentNode,
 | 
						|
             AML_HAS_FIELD_LIST
 | 
						|
             ))
 | 
						|
      {
 | 
						|
        ASSERT (0);
 | 
						|
        return EFI_INVALID_PARAMETER;
 | 
						|
      }
 | 
						|
 | 
						|
      // Fall through.
 | 
						|
    }
 | 
						|
 | 
						|
    case EAmlUInt8:
 | 
						|
    case EAmlUInt16:
 | 
						|
    case EAmlUInt32:
 | 
						|
    case EAmlUInt64:
 | 
						|
    case EAmlName:
 | 
						|
    case EAmlString:
 | 
						|
    {
 | 
						|
      // A uint, a name, a string and a FieldPkgLen can only be replaced by a
 | 
						|
      // data node of the same type.
 | 
						|
      // Note: This condition might be too strict, but safer.
 | 
						|
      if (!IS_AML_DATA_NODE (NewNode) ||
 | 
						|
          (((AML_DATA_NODE *)NewNode)->DataType !=
 | 
						|
           AmlTypeToNodeDataType (FixedArgType)))
 | 
						|
      {
 | 
						|
        ASSERT (0);
 | 
						|
        return EFI_INVALID_PARAMETER;
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case EAmlObject:
 | 
						|
    {
 | 
						|
      // If it's an object node, the grammar is too complex to do any check.
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    case EAmlNone:
 | 
						|
    default:
 | 
						|
    {
 | 
						|
      ASSERT (0);
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  } // switch
 | 
						|
 | 
						|
  // Replace the OldNode with the NewNode.
 | 
						|
  OldNode = AmlGetFixedArgument (ParentNode, Index);
 | 
						|
  if (!IS_AML_NODE_VALID (OldNode)) {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  // Unlink the old node.
 | 
						|
  // Note: This function unlinks the OldNode from the tree. It is the callers
 | 
						|
  //       responsibility to delete the OldNode if needed.
 | 
						|
  OldNode->Parent = NULL;
 | 
						|
 | 
						|
  Status = AmlSetFixedArgument (ParentNode, Index, NewNode);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    ASSERT (0);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  // Get the size of the OldNode.
 | 
						|
  Status = AmlComputeSize (OldNode, &OldSize);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    ASSERT (0);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  // Get the size of the NewNode.
 | 
						|
  Status = AmlComputeSize (NewNode, &NewSize);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    ASSERT (0);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  // Propagate the new information.
 | 
						|
  Status = AmlPropagateInformation (
 | 
						|
             (AML_NODE_HEADER *)ParentNode,
 | 
						|
             (NewSize > OldSize) ? TRUE : FALSE,
 | 
						|
             (NewSize > OldSize) ? (NewSize - OldSize) : (OldSize - NewSize),
 | 
						|
             0
 | 
						|
             );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/** Replace the OldNode, which is in a variable list of arguments,
 | 
						|
    with the NewNode.
 | 
						|
 | 
						|
  Note: This function unlinks the OldNode from the tree. It is the callers
 | 
						|
        responsibility to delete the OldNode if needed.
 | 
						|
 | 
						|
  @param  [in]  OldNode   Pointer to the node to replace.
 | 
						|
                          Must be a data node or an object node.
 | 
						|
  @param  [in]  NewNode   The new node to insert.
 | 
						|
                          Must be a data node or an object node.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The function completed successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AmlReplaceVariableArgument (
 | 
						|
  IN  AML_NODE_HEADER  *OldNode,
 | 
						|
  IN  AML_NODE_HEADER  *NewNode
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS        Status;
 | 
						|
  UINT32            NewSize;
 | 
						|
  UINT32            OldSize;
 | 
						|
  EAML_PARSE_INDEX  Index;
 | 
						|
 | 
						|
  AML_DATA_NODE    *NewDataNode;
 | 
						|
  AML_NODE_HEADER  *ParentNode;
 | 
						|
  LIST_ENTRY       *NextLink;
 | 
						|
 | 
						|
  // Check arguments, that NewNode is not already attached to a tree,
 | 
						|
  // and that OldNode is attached and not in a fixed list of arguments.
 | 
						|
  if ((!IS_AML_DATA_NODE (OldNode)      &&
 | 
						|
       !IS_AML_OBJECT_NODE (OldNode))   ||
 | 
						|
      (!IS_AML_DATA_NODE (NewNode)      &&
 | 
						|
       !IS_AML_OBJECT_NODE (NewNode))   ||
 | 
						|
      !AML_NODE_IS_DETACHED (NewNode)   ||
 | 
						|
      AML_NODE_IS_DETACHED (OldNode)    ||
 | 
						|
      AmlIsNodeFixedArgument (OldNode, &Index))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  ParentNode = AmlGetParent (OldNode);
 | 
						|
  if (!IS_AML_ROOT_NODE (ParentNode)    &&
 | 
						|
      !IS_AML_OBJECT_NODE (ParentNode))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  NewDataNode = (AML_DATA_NODE *)NewNode;
 | 
						|
 | 
						|
  // Check attributes if the parent node is an object node.
 | 
						|
  if (IS_AML_OBJECT_NODE (ParentNode)) {
 | 
						|
    // A child node of a node with the HAS_CHILD flag must be either a
 | 
						|
    // data node or an object node. This has already been checked. So,
 | 
						|
    // check for other cases.
 | 
						|
 | 
						|
    if (AmlNodeHasAttribute ((AML_OBJECT_NODE *)ParentNode, AML_HAS_BYTE_LIST)) {
 | 
						|
      if (!IS_AML_DATA_NODE (NewNode)                       ||
 | 
						|
          ((NewDataNode->DataType != EAmlNodeDataTypeRaw)   &&
 | 
						|
           (NewDataNode->DataType != EAmlNodeDataTypeResourceData)))
 | 
						|
      {
 | 
						|
        // A child node of a node with the BYTE_LIST flag must be a data node,
 | 
						|
        // containing raw data or a resource data.
 | 
						|
        ASSERT (0);
 | 
						|
        return EFI_INVALID_PARAMETER;
 | 
						|
      }
 | 
						|
    } else if (AmlNodeHasAttribute (
 | 
						|
                 (AML_OBJECT_NODE *)ParentNode,
 | 
						|
                 AML_HAS_FIELD_LIST
 | 
						|
                 ))
 | 
						|
    {
 | 
						|
      if (!AmlNodeHasAttribute (
 | 
						|
             (CONST AML_OBJECT_NODE *)NewNode,
 | 
						|
             AML_IS_FIELD_ELEMENT
 | 
						|
             ))
 | 
						|
      {
 | 
						|
        // A child node of a node with the FIELD_LIST flag must be an object
 | 
						|
        // node with AML_IS_FIELD_ELEMENT flag.
 | 
						|
        ASSERT (0);
 | 
						|
        return EFI_INVALID_PARAMETER;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    // Parent node is a root node.
 | 
						|
    // A root node cannot have a data node as its child.
 | 
						|
    if (!IS_AML_DATA_NODE (NewNode)) {
 | 
						|
      ASSERT (0);
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Unlink OldNode from the tree.
 | 
						|
  NextLink = RemoveEntryList (&OldNode->Link);
 | 
						|
  InitializeListHead (&OldNode->Link);
 | 
						|
  OldNode->Parent = NULL;
 | 
						|
 | 
						|
  // Add the NewNode.
 | 
						|
  InsertHeadList (NextLink, &NewNode->Link);
 | 
						|
  NewNode->Parent = ParentNode;
 | 
						|
 | 
						|
  // Get the size of the OldNode.
 | 
						|
  Status = AmlComputeSize (OldNode, &OldSize);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    ASSERT (0);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  // Get the size of the NewNode.
 | 
						|
  Status = AmlComputeSize (NewNode, &NewSize);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    ASSERT (0);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  // Propagate the new information.
 | 
						|
  Status = AmlPropagateInformation (
 | 
						|
             ParentNode,
 | 
						|
             (NewSize > OldSize) ? TRUE : FALSE,
 | 
						|
             (NewSize > OldSize) ? (NewSize - OldSize) : (OldSize - NewSize),
 | 
						|
             0
 | 
						|
             );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/** Replace the OldNode by the NewNode.
 | 
						|
 | 
						|
  Note: This function unlinks the OldNode from the tree. It is the callers
 | 
						|
        responsibility to delete the OldNode if needed.
 | 
						|
 | 
						|
  @param  [in]  OldNode   Pointer to the node to replace.
 | 
						|
                          Must be a data node or an object node.
 | 
						|
  @param  [in]  NewNode   The new node to insert.
 | 
						|
                          Must be a data node or an object node.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The function completed successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AmlReplaceArgument (
 | 
						|
  IN  AML_NODE_HEADER  *OldNode,
 | 
						|
  IN  AML_NODE_HEADER  *NewNode
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS        Status;
 | 
						|
  AML_NODE_HEADER   *ParentNode;
 | 
						|
  EAML_PARSE_INDEX  Index;
 | 
						|
 | 
						|
  // Check arguments and that NewNode is not already attached to a tree.
 | 
						|
  if ((!IS_AML_DATA_NODE (OldNode)      &&
 | 
						|
       !IS_AML_OBJECT_NODE (OldNode))   ||
 | 
						|
      (!IS_AML_DATA_NODE (NewNode)      &&
 | 
						|
       !IS_AML_OBJECT_NODE (NewNode))   ||
 | 
						|
      !AML_NODE_IS_DETACHED (NewNode))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  // ParentNode can be a root node or an object node.
 | 
						|
  ParentNode = AmlGetParent (OldNode);
 | 
						|
  if (!IS_AML_ROOT_NODE (ParentNode)  &&
 | 
						|
      !IS_AML_OBJECT_NODE (ParentNode))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (AmlIsNodeFixedArgument (OldNode, &Index)) {
 | 
						|
    // OldNode is in its parent's fixed argument list at the Index.
 | 
						|
    Status = AmlReplaceFixedArgument (
 | 
						|
               (AML_OBJECT_NODE *)ParentNode,
 | 
						|
               Index,
 | 
						|
               NewNode
 | 
						|
               );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      ASSERT (0);
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    // OldNode is not in its parent's fixed argument list.
 | 
						|
    // It must be in its variable list of arguments.
 | 
						|
    Status = AmlReplaceVariableArgument (OldNode, NewNode);
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/** Delete a Node and its children.
 | 
						|
 | 
						|
  The Node must be removed from the tree first,
 | 
						|
  or must be the root node.
 | 
						|
 | 
						|
  @param  [in]  Node  Pointer to the node to delete.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The function completed successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AmlDeleteTree (
 | 
						|
  IN  AML_NODE_HEADER  *Node
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  EAML_PARSE_INDEX  Index;
 | 
						|
  EAML_PARSE_INDEX  MaxIndex;
 | 
						|
 | 
						|
  AML_NODE_HEADER  *Arg;
 | 
						|
  LIST_ENTRY       *StartLink;
 | 
						|
  LIST_ENTRY       *CurrentLink;
 | 
						|
  LIST_ENTRY       *NextLink;
 | 
						|
 | 
						|
  // Check that the node being deleted is unlinked.
 | 
						|
  // When removing the node, its parent pointer and
 | 
						|
  // its lists data structure are reset with
 | 
						|
  // InitializeListHead. Thus it must be detached
 | 
						|
  // from the tree to avoid memory leaks.
 | 
						|
  if (!IS_AML_NODE_VALID (Node)  ||
 | 
						|
      !AML_NODE_IS_DETACHED (Node))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  // 1. Recursively detach and delete the fixed arguments.
 | 
						|
  //    Iterate through the fixed list of arguments.
 | 
						|
  if (IS_AML_OBJECT_NODE (Node)) {
 | 
						|
    MaxIndex = (EAML_PARSE_INDEX)AmlGetFixedArgumentCount (
 | 
						|
                                   (AML_OBJECT_NODE *)Node
 | 
						|
                                   );
 | 
						|
    for (Index = EAmlParseIndexTerm0; Index < MaxIndex; Index++) {
 | 
						|
      Arg = AmlGetFixedArgument ((AML_OBJECT_NODE *)Node, Index);
 | 
						|
      if (Arg == NULL) {
 | 
						|
        // A fixed argument is missing. The tree is inconsistent.
 | 
						|
        // Note: During CodeGeneration, the fixed arguments should be set
 | 
						|
        //       with an incrementing index, and then the variable arguments
 | 
						|
        //       should be added. This allows to free as many nodes as
 | 
						|
        //       possible if a crash occurs.
 | 
						|
        ASSERT (0);
 | 
						|
        return EFI_INVALID_PARAMETER;
 | 
						|
      }
 | 
						|
 | 
						|
      // Remove the node from the fixed argument list.
 | 
						|
      Arg->Parent = NULL;
 | 
						|
      Status      = AmlSetFixedArgument ((AML_OBJECT_NODE *)Node, Index, NULL);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        ASSERT (0);
 | 
						|
        return Status;
 | 
						|
      }
 | 
						|
 | 
						|
      Status = AmlDeleteTree (Arg);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        ASSERT (0);
 | 
						|
        return Status;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // 2. Recursively detach and delete the variable arguments.
 | 
						|
  //    Iterate through the variable list of arguments.
 | 
						|
  StartLink = AmlNodeGetVariableArgList (Node);
 | 
						|
  if (StartLink != NULL) {
 | 
						|
    NextLink = StartLink->ForwardLink;
 | 
						|
    while (NextLink != StartLink) {
 | 
						|
      CurrentLink = NextLink;
 | 
						|
 | 
						|
      // Unlink the node from the tree.
 | 
						|
      NextLink = RemoveEntryList (CurrentLink);
 | 
						|
      InitializeListHead (CurrentLink);
 | 
						|
      ((AML_NODE_HEADER *)CurrentLink)->Parent = NULL;
 | 
						|
 | 
						|
      Status = AmlDeleteTree ((AML_NODE_HEADER *)CurrentLink);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        ASSERT (0);
 | 
						|
        return Status;
 | 
						|
      }
 | 
						|
    } // while
 | 
						|
  }
 | 
						|
 | 
						|
  // 3. Delete the node.
 | 
						|
  Status = AmlDeleteNode (Node);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 |