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>
		
			
				
	
	
		
			1012 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1012 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  AML Utility.
 | 
						|
 | 
						|
  Copyright (c) 2019 - 2021, Arm Limited. All rights reserved.<BR>
 | 
						|
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
**/
 | 
						|
 | 
						|
#include <Utils/AmlUtility.h>
 | 
						|
 | 
						|
#include <AmlCoreInterface.h>
 | 
						|
#include <Tree/AmlNode.h>
 | 
						|
#include <Tree/AmlTree.h>
 | 
						|
 | 
						|
/** This function computes and updates the ACPI table checksum.
 | 
						|
 | 
						|
  @param  [in]  AcpiTable   Pointer to an Acpi table.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS   The function completed successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AcpiPlatformChecksum (
 | 
						|
  IN  EFI_ACPI_DESCRIPTION_HEADER  *AcpiTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8   *Ptr;
 | 
						|
  UINT8   Sum;
 | 
						|
  UINT32  Size;
 | 
						|
 | 
						|
  if (AcpiTable == NULL) {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Ptr  = (UINT8 *)AcpiTable;
 | 
						|
  Size = AcpiTable->Length;
 | 
						|
  Sum  = 0;
 | 
						|
 | 
						|
  // Set the checksum field to 0 first.
 | 
						|
  AcpiTable->Checksum = 0;
 | 
						|
 | 
						|
  // Compute the checksum.
 | 
						|
  while ((Size--) != 0) {
 | 
						|
    Sum = (UINT8)(Sum + (*Ptr++));
 | 
						|
  }
 | 
						|
 | 
						|
  // Set the checksum.
 | 
						|
  AcpiTable->Checksum = (UINT8)(0xFF - Sum + 1);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/** A callback function that computes the size of a Node and adds it to the
 | 
						|
    Size pointer stored in the Context.
 | 
						|
    Calling this function on the root node will compute the total size of the
 | 
						|
    AML bytestream.
 | 
						|
 | 
						|
  @param  [in]      Node      Node to compute the size.
 | 
						|
  @param  [in, out] Context   Pointer holding the computed size.
 | 
						|
                              (UINT32 *) Context.
 | 
						|
  @param  [in, out] Status    Pointer holding:
 | 
						|
                               - At entry, the Status returned by the
 | 
						|
                                 last call to this exact function during
 | 
						|
                                 the enumeration;
 | 
						|
                               - At exit, he returned status of the
 | 
						|
                                 call to this function.
 | 
						|
                              Optional, can be NULL.
 | 
						|
 | 
						|
  @retval TRUE if the enumeration can continue or has finished without
 | 
						|
          interruption.
 | 
						|
  @retval FALSE if the enumeration needs to stopped or has stopped.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
BOOLEAN
 | 
						|
EFIAPI
 | 
						|
AmlComputeSizeCallback (
 | 
						|
  IN      AML_NODE_HEADER  *Node,
 | 
						|
  IN  OUT VOID             *Context,
 | 
						|
  IN  OUT EFI_STATUS       *Status   OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32                 Size;
 | 
						|
  EAML_PARSE_INDEX       IndexPtr;
 | 
						|
  CONST AML_OBJECT_NODE  *ParentNode;
 | 
						|
 | 
						|
  if (!IS_AML_NODE_VALID (Node) ||
 | 
						|
      (Context == NULL))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    if (Status != NULL) {
 | 
						|
      *Status = EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  // Ignore the second fixed argument of method invocation nodes
 | 
						|
  // as the information stored there (the argument count) is not in the
 | 
						|
  // ACPI specification.
 | 
						|
  ParentNode = (CONST AML_OBJECT_NODE *)AmlGetParent (Node);
 | 
						|
  if (IS_AML_OBJECT_NODE (ParentNode)                             &&
 | 
						|
      AmlNodeCompareOpCode (ParentNode, AML_METHOD_INVOC_OP, 0)   &&
 | 
						|
      AmlIsNodeFixedArgument (Node, &IndexPtr))
 | 
						|
  {
 | 
						|
    if (IndexPtr == EAmlParseIndexTerm1) {
 | 
						|
      if (Status != NULL) {
 | 
						|
        *Status = EFI_SUCCESS;
 | 
						|
      }
 | 
						|
 | 
						|
      return TRUE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Size = *((UINT32 *)Context);
 | 
						|
 | 
						|
  if (IS_AML_DATA_NODE (Node)) {
 | 
						|
    Size += ((AML_DATA_NODE *)Node)->Size;
 | 
						|
  } else if (IS_AML_OBJECT_NODE (Node)  &&
 | 
						|
             !AmlNodeHasAttribute (
 | 
						|
                (CONST AML_OBJECT_NODE *)Node,
 | 
						|
                AML_IS_PSEUDO_OPCODE
 | 
						|
                ))
 | 
						|
  {
 | 
						|
    // Ignore pseudo-opcodes as they are not part of the
 | 
						|
    // ACPI specification.
 | 
						|
 | 
						|
    Size += (((AML_OBJECT_NODE *)Node)->AmlByteEncoding->OpCode ==
 | 
						|
             AML_EXT_OP) ? 2 : 1;
 | 
						|
 | 
						|
    // Add the size of the PkgLen.
 | 
						|
    if (AmlNodeHasAttribute (
 | 
						|
          (AML_OBJECT_NODE *)Node,
 | 
						|
          AML_HAS_PKG_LENGTH
 | 
						|
          ))
 | 
						|
    {
 | 
						|
      Size += AmlComputePkgLengthWidth (((AML_OBJECT_NODE *)Node)->PkgLen);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Check for overflow.
 | 
						|
  // The root node has a null size, thus the strict comparison.
 | 
						|
  if (*((UINT32 *)Context) > Size) {
 | 
						|
    ASSERT (0);
 | 
						|
    *Status = EFI_INVALID_PARAMETER;
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  *((UINT32 *)Context) = Size;
 | 
						|
 | 
						|
  if (Status != NULL) {
 | 
						|
    *Status = EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/** Compute the size of a tree/sub-tree.
 | 
						|
 | 
						|
  @param  [in]      Node      Node to compute the size.
 | 
						|
  @param  [in, out] Size      Pointer holding the computed size.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The function completed successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AmlComputeSize (
 | 
						|
  IN      CONST AML_NODE_HEADER  *Node,
 | 
						|
  IN  OUT       UINT32           *Size
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  if (!IS_AML_NODE_VALID (Node) ||
 | 
						|
      (Size == NULL))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  *Size = 0;
 | 
						|
 | 
						|
  AmlEnumTree (
 | 
						|
    (AML_NODE_HEADER *)Node,
 | 
						|
    AmlComputeSizeCallback,
 | 
						|
    (VOID *)Size,
 | 
						|
    &Status
 | 
						|
    );
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/** Get the value contained in an integer node.
 | 
						|
 | 
						|
  @param  [in]  Node    Pointer to an integer node.
 | 
						|
                        Must be an object node.
 | 
						|
  @param  [out] Value   Value contained in the integer node.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The function completed successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AmlNodeGetIntegerValue (
 | 
						|
  IN  AML_OBJECT_NODE  *Node,
 | 
						|
  OUT UINT64           *Value
 | 
						|
  )
 | 
						|
{
 | 
						|
  AML_DATA_NODE  *DataNode;
 | 
						|
 | 
						|
  if ((!IsIntegerNode (Node)            &&
 | 
						|
       !IsSpecialIntegerNode (Node))    ||
 | 
						|
      (Value == NULL))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  // For ZeroOp and OneOp, there is no data node.
 | 
						|
  if (IsSpecialIntegerNode (Node)) {
 | 
						|
    if (AmlNodeCompareOpCode (Node, AML_ZERO_OP, 0)) {
 | 
						|
      *Value = 0;
 | 
						|
    } else if (AmlNodeCompareOpCode (Node, AML_ONE_OP, 0)) {
 | 
						|
      *Value = 1;
 | 
						|
    } else {
 | 
						|
      // OnesOp cannot be handled: it represents a maximum value.
 | 
						|
      ASSERT (0);
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  // For integer nodes, the value is in the first fixed argument.
 | 
						|
  DataNode = (AML_DATA_NODE *)Node->FixedArgs[EAmlParseIndexTerm0];
 | 
						|
  if (!IS_AML_DATA_NODE (DataNode) ||
 | 
						|
      (DataNode->DataType != EAmlNodeDataTypeUInt))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  switch (DataNode->Size) {
 | 
						|
    case 1:
 | 
						|
    {
 | 
						|
      *Value = *((UINT8 *)(DataNode->Buffer));
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    case 2:
 | 
						|
    {
 | 
						|
      *Value = *((UINT16 *)(DataNode->Buffer));
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    case 4:
 | 
						|
    {
 | 
						|
      *Value = *((UINT32 *)(DataNode->Buffer));
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    case 8:
 | 
						|
    {
 | 
						|
      *Value = *((UINT64 *)(DataNode->Buffer));
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
    {
 | 
						|
      ASSERT (0);
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
  } // switch
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/** Replace a Zero (AML_ZERO_OP) or One (AML_ONE_OP) object node
 | 
						|
    with a byte integer (AML_BYTE_PREFIX) object node having the same value.
 | 
						|
 | 
						|
  @param  [in]  Node    Pointer to an integer node.
 | 
						|
                        Must be an object node having ZeroOp or OneOp.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The function completed successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AmlUnwindSpecialInteger (
 | 
						|
  IN  AML_OBJECT_NODE  *Node
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  AML_DATA_NODE            *NewDataNode;
 | 
						|
  UINT8                    Value;
 | 
						|
  CONST AML_BYTE_ENCODING  *ByteEncoding;
 | 
						|
 | 
						|
  if (!IsSpecialIntegerNode (Node)) {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  // Find the value.
 | 
						|
  if (AmlNodeCompareOpCode (Node, AML_ZERO_OP, 0)) {
 | 
						|
    Value = 0;
 | 
						|
  } else if (AmlNodeCompareOpCode (Node, AML_ONE_OP, 0)) {
 | 
						|
    Value = 1;
 | 
						|
  } else {
 | 
						|
    // OnesOp cannot be handled: it represents a maximum value.
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = AmlCreateDataNode (
 | 
						|
             EAmlNodeDataTypeUInt,
 | 
						|
             &Value,
 | 
						|
             sizeof (UINT8),
 | 
						|
             (AML_DATA_NODE **)&NewDataNode
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    ASSERT (0);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  // Change the encoding of the special node to a ByteOp encoding.
 | 
						|
  ByteEncoding = AmlGetByteEncodingByOpCode (AML_BYTE_PREFIX, 0);
 | 
						|
  if (ByteEncoding == NULL) {
 | 
						|
    ASSERT (0);
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto error_handler;
 | 
						|
  }
 | 
						|
 | 
						|
  // Update the ByteEncoding from ZERO_OP/ONE_OP to AML_BYTE_PREFIX.
 | 
						|
  Node->AmlByteEncoding = ByteEncoding;
 | 
						|
 | 
						|
  // Add the data node as the first fixed argument of the ByteOp object.
 | 
						|
  Status = AmlSetFixedArgument (
 | 
						|
             (AML_OBJECT_NODE *)Node,
 | 
						|
             EAmlParseIndexTerm0,
 | 
						|
             (AML_NODE_HEADER *)NewDataNode
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    ASSERT (0);
 | 
						|
    goto error_handler;
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
 | 
						|
error_handler:
 | 
						|
  AmlDeleteTree ((AML_NODE_HEADER *)NewDataNode);
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/** Set the value contained in an integer node.
 | 
						|
 | 
						|
  The OpCode is updated accordingly to the new value
 | 
						|
  (e.g.: If the original value was a UINT8 value, then the OpCode
 | 
						|
         would be AML_BYTE_PREFIX. If it the new value is a UINT16
 | 
						|
         value then the OpCode will be updated to AML_WORD_PREFIX).
 | 
						|
 | 
						|
  @param  [in]  Node            Pointer to an integer node.
 | 
						|
                                Must be an object node.
 | 
						|
  @param  [in]  NewValue        New value to write in the integer node.
 | 
						|
  @param  [out] ValueWidthDiff  Difference in number of bytes used to store
 | 
						|
                                the new value.
 | 
						|
                                Can be negative.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The function completed successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AmlNodeSetIntegerValue (
 | 
						|
  IN  AML_OBJECT_NODE  *Node,
 | 
						|
  IN  UINT64           NewValue,
 | 
						|
  OUT INT8             *ValueWidthDiff
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS     Status;
 | 
						|
  AML_DATA_NODE  *DataNode;
 | 
						|
 | 
						|
  UINT8  NewOpCode;
 | 
						|
  UINT8  NumberOfBytes;
 | 
						|
 | 
						|
  if ((!IsIntegerNode (Node)            &&
 | 
						|
       !IsSpecialIntegerNode (Node))    ||
 | 
						|
      (ValueWidthDiff == NULL))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  *ValueWidthDiff = 0;
 | 
						|
  // For ZeroOp and OneOp, there is no data node.
 | 
						|
  // Thus the object node is converted to a byte object node holding 0 or 1.
 | 
						|
  if (IsSpecialIntegerNode (Node)) {
 | 
						|
    switch (NewValue) {
 | 
						|
      case AML_ZERO_OP:
 | 
						|
        Node->AmlByteEncoding = AmlGetByteEncodingByOpCode (AML_ZERO_OP, 0);
 | 
						|
        return EFI_SUCCESS;
 | 
						|
      case AML_ONE_OP:
 | 
						|
        Node->AmlByteEncoding = AmlGetByteEncodingByOpCode (AML_ONE_OP, 0);
 | 
						|
        return EFI_SUCCESS;
 | 
						|
      default:
 | 
						|
      {
 | 
						|
        Status = AmlUnwindSpecialInteger (Node);
 | 
						|
        if (EFI_ERROR (Status)) {
 | 
						|
          ASSERT (0);
 | 
						|
          return Status;
 | 
						|
        }
 | 
						|
 | 
						|
        // The AmlUnwindSpecialInteger functions converts a special integer
 | 
						|
        // node to a UInt8/Byte data node. Thus, the size increments by one:
 | 
						|
        // special integer are encoded as one byte (the opcode only) while byte
 | 
						|
        // integers are encoded as two bytes (the opcode + the value).
 | 
						|
        *ValueWidthDiff += sizeof (UINT8);
 | 
						|
      }
 | 
						|
    } // switch
 | 
						|
  } // IsSpecialIntegerNode (Node)
 | 
						|
 | 
						|
  // For integer nodes, the value is in the first fixed argument.
 | 
						|
  DataNode = (AML_DATA_NODE *)Node->FixedArgs[EAmlParseIndexTerm0];
 | 
						|
  if (!IS_AML_DATA_NODE (DataNode) ||
 | 
						|
      (DataNode->DataType != EAmlNodeDataTypeUInt))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  // The value can be encoded with a special 0 or 1 OpCode.
 | 
						|
  // The AML_ONES_OP is not handled.
 | 
						|
  if (NewValue <= 1) {
 | 
						|
    NewOpCode             = (NewValue == 0) ? AML_ZERO_OP : AML_ONE_OP;
 | 
						|
    Node->AmlByteEncoding = AmlGetByteEncodingByOpCode (NewOpCode, 0);
 | 
						|
 | 
						|
    // The value is encoded with a AML_ZERO_OP or AML_ONE_OP.
 | 
						|
    // This means there is no need for a DataNode containing the value.
 | 
						|
    // The change in size is equal to the size of the DataNode's buffer.
 | 
						|
    *ValueWidthDiff = -((INT8)DataNode->Size);
 | 
						|
 | 
						|
    // Detach and free the DataNode containing the integer value.
 | 
						|
    DataNode->NodeHeader.Parent          = NULL;
 | 
						|
    Node->FixedArgs[EAmlParseIndexTerm0] = NULL;
 | 
						|
    Status                               = AmlDeleteNode ((AML_NODE_HEADER *)DataNode);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      ASSERT (0);
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  // Check the number of bits needed to represent the value.
 | 
						|
  if (NewValue > MAX_UINT32) {
 | 
						|
    // Value is 64 bits.
 | 
						|
    NewOpCode     = AML_QWORD_PREFIX;
 | 
						|
    NumberOfBytes = 8;
 | 
						|
  } else if (NewValue > MAX_UINT16) {
 | 
						|
    // Value is 32 bits.
 | 
						|
    NewOpCode     = AML_DWORD_PREFIX;
 | 
						|
    NumberOfBytes = 4;
 | 
						|
  } else if (NewValue > MAX_UINT8) {
 | 
						|
    // Value is 16 bits.
 | 
						|
    NewOpCode     = AML_WORD_PREFIX;
 | 
						|
    NumberOfBytes = 2;
 | 
						|
  } else {
 | 
						|
    // Value is 8 bits.
 | 
						|
    NewOpCode     = AML_BYTE_PREFIX;
 | 
						|
    NumberOfBytes = 1;
 | 
						|
  }
 | 
						|
 | 
						|
  *ValueWidthDiff += (INT8)(NumberOfBytes - DataNode->Size);
 | 
						|
 | 
						|
  // Update the ByteEncoding as it may have changed between [8 .. 64] bits.
 | 
						|
  Node->AmlByteEncoding = AmlGetByteEncodingByOpCode (NewOpCode, 0);
 | 
						|
  if (Node->AmlByteEncoding == NULL) {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  // Free the old DataNode buffer and allocate a buffer with the right size
 | 
						|
  // to store the new data.
 | 
						|
  if (*ValueWidthDiff != 0) {
 | 
						|
    FreePool (DataNode->Buffer);
 | 
						|
    DataNode->Buffer = AllocateZeroPool (NumberOfBytes);
 | 
						|
    if (DataNode->Buffer == NULL) {
 | 
						|
      ASSERT (0);
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
 | 
						|
    DataNode->Size = NumberOfBytes;
 | 
						|
  }
 | 
						|
 | 
						|
  // Write the new value.
 | 
						|
  CopyMem (DataNode->Buffer, &NewValue, NumberOfBytes);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/** Increment/decrement the value contained in the IntegerNode.
 | 
						|
 | 
						|
  @param  [in]  IntegerNode     Pointer to an object node containing
 | 
						|
                                an integer.
 | 
						|
  @param  [in]  IsIncrement     Choose the operation to do:
 | 
						|
                                 - TRUE:  Increment the Node's size and
 | 
						|
                                          the Node's count;
 | 
						|
                                 - FALSE: Decrement the Node's size and
 | 
						|
                                          the Node's count.
 | 
						|
  @param  [in]  Diff            Value to add/subtract to the integer.
 | 
						|
  @param  [out] ValueWidthDiff  When modifying the integer, it can be
 | 
						|
                                promoted/demoted, e.g. from UINT8 to UINT16.
 | 
						|
                                Stores the change in width.
 | 
						|
                                Can be negative.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The function completed successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AmlNodeUpdateIntegerValue (
 | 
						|
  IN  AML_OBJECT_NODE  *IntegerNode,
 | 
						|
  IN  BOOLEAN          IsIncrement,
 | 
						|
  IN  UINT64           Diff,
 | 
						|
  OUT INT8             *ValueWidthDiff
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  UINT64      Value;
 | 
						|
 | 
						|
  if (ValueWidthDiff == NULL) {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  // Get the current value.
 | 
						|
  // Checks on the IntegerNode are done in the call.
 | 
						|
  Status = AmlNodeGetIntegerValue (IntegerNode, &Value);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    ASSERT (0);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  // Check for UINT64 over/underflow.
 | 
						|
  if ((IsIncrement && (Value > (MAX_UINT64 - Diff))) ||
 | 
						|
      (!IsIncrement && (Value < Diff)))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  // Compute the new value.
 | 
						|
  if (IsIncrement) {
 | 
						|
    Value += Diff;
 | 
						|
  } else {
 | 
						|
    Value -= Diff;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = AmlNodeSetIntegerValue (
 | 
						|
             IntegerNode,
 | 
						|
             Value,
 | 
						|
             ValueWidthDiff
 | 
						|
             );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/** Propagate the size information up the tree.
 | 
						|
 | 
						|
  The length of the ACPI table is updated in the RootNode,
 | 
						|
  but not the checksum.
 | 
						|
 | 
						|
  @param  [in]  Node          Pointer to a node.
 | 
						|
                              Must be a root node or an object node.
 | 
						|
  @param  [in]  IsIncrement   Choose the operation to do:
 | 
						|
                               - TRUE:  Increment the Node's size and
 | 
						|
                                        the Node's count;
 | 
						|
                               - FALSE: Decrement the Node's size and
 | 
						|
                                        the Node's count.
 | 
						|
  @param  [in]  Diff          Value to add/subtract to the Node's size.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The function completed successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AmlPropagateSize (
 | 
						|
  IN  AML_NODE_HEADER  *Node,
 | 
						|
  IN  BOOLEAN          IsIncrement,
 | 
						|
  IN  UINT32           *Diff
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS       Status;
 | 
						|
  AML_OBJECT_NODE  *ObjectNode;
 | 
						|
  AML_NODE_HEADER  *ParentNode;
 | 
						|
 | 
						|
  UINT32  Value;
 | 
						|
  UINT32  InitialPkgLenWidth;
 | 
						|
  UINT32  NewPkgLenWidth;
 | 
						|
  UINT32  ReComputedPkgLenWidth;
 | 
						|
  INT8    FieldWidthChange;
 | 
						|
 | 
						|
  if (!IS_AML_OBJECT_NODE (Node) &&
 | 
						|
      !IS_AML_ROOT_NODE (Node))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (IS_AML_OBJECT_NODE (Node)) {
 | 
						|
    ObjectNode = (AML_OBJECT_NODE *)Node;
 | 
						|
 | 
						|
    // For BufferOp, the buffer size is stored in BufferSize. Therefore,
 | 
						|
    // BufferOp needs special handling to update the BufferSize.
 | 
						|
    // BufferSize must be updated before the PkgLen to accommodate any
 | 
						|
    // increment resulting from the update of the BufferSize.
 | 
						|
    // DefBuffer := BufferOp PkgLength BufferSize ByteList
 | 
						|
    // BufferOp := 0x11
 | 
						|
    // BufferSize := TermArg => Integer
 | 
						|
    if (AmlNodeCompareOpCode (ObjectNode, AML_BUFFER_OP, 0)) {
 | 
						|
      // First fixed argument of BufferOp is an integer (BufferSize)
 | 
						|
      // (can be a BYTE, WORD, DWORD or QWORD).
 | 
						|
      // BufferSize is an object node.
 | 
						|
      Status = AmlNodeUpdateIntegerValue (
 | 
						|
                 (AML_OBJECT_NODE *)AmlGetFixedArgument (
 | 
						|
                                      ObjectNode,
 | 
						|
                                      EAmlParseIndexTerm0
 | 
						|
                                      ),
 | 
						|
                 IsIncrement,
 | 
						|
                 (UINT64)(*Diff),
 | 
						|
                 &FieldWidthChange
 | 
						|
                 );
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        ASSERT (0);
 | 
						|
        return Status;
 | 
						|
      }
 | 
						|
 | 
						|
      // FieldWidthChange is an integer.
 | 
						|
      // It must be positive if IsIncrement is TRUE, negative otherwise.
 | 
						|
      if ((IsIncrement              &&
 | 
						|
           (FieldWidthChange < 0))  ||
 | 
						|
          (!IsIncrement             &&
 | 
						|
           (FieldWidthChange > 0)))
 | 
						|
      {
 | 
						|
        ASSERT (0);
 | 
						|
        return EFI_INVALID_PARAMETER;
 | 
						|
      }
 | 
						|
 | 
						|
      // Check for UINT32 overflow.
 | 
						|
      if (*Diff > (MAX_UINT32 - (UINT32)ABS (FieldWidthChange))) {
 | 
						|
        ASSERT (0);
 | 
						|
        return EFI_INVALID_PARAMETER;
 | 
						|
      }
 | 
						|
 | 
						|
      // Update Diff if the field width changed.
 | 
						|
      *Diff = (UINT32)(*Diff + ABS (FieldWidthChange));
 | 
						|
    } // AML_BUFFER_OP node.
 | 
						|
 | 
						|
    // Update the PgkLen.
 | 
						|
    // Needs to be done at last to reflect the potential field width changes.
 | 
						|
    if (AmlNodeHasAttribute (ObjectNode, AML_HAS_PKG_LENGTH)) {
 | 
						|
      Value = ObjectNode->PkgLen;
 | 
						|
 | 
						|
      // Subtract the size of the PkgLen encoding. The size of the PkgLen
 | 
						|
      // encoding must be computed after having updated Value.
 | 
						|
      InitialPkgLenWidth = AmlComputePkgLengthWidth (Value);
 | 
						|
      Value             -= InitialPkgLenWidth;
 | 
						|
 | 
						|
      // Check for an over/underflows.
 | 
						|
      // PkgLen is a 28 bit value, cf 20.2.4 Package Length Encoding
 | 
						|
      // i.e. the maximum value is (2^28 - 1) = ((BIT0 << 28) - 1).
 | 
						|
      if ((IsIncrement && ((((BIT0 << 28) - 1) - Value) < *Diff))   ||
 | 
						|
          (!IsIncrement && (Value < *Diff)))
 | 
						|
      {
 | 
						|
        ASSERT (0);
 | 
						|
        return EFI_INVALID_PARAMETER;
 | 
						|
      }
 | 
						|
 | 
						|
      // Update the size.
 | 
						|
      if (IsIncrement) {
 | 
						|
        Value += *Diff;
 | 
						|
      } else {
 | 
						|
        Value -= *Diff;
 | 
						|
      }
 | 
						|
 | 
						|
      // Compute the new PkgLenWidth.
 | 
						|
      NewPkgLenWidth = AmlComputePkgLengthWidth (Value);
 | 
						|
      if (NewPkgLenWidth == 0) {
 | 
						|
        ASSERT (0);
 | 
						|
        return EFI_INVALID_PARAMETER;
 | 
						|
      }
 | 
						|
 | 
						|
      // Add it to the Value.
 | 
						|
      Value += NewPkgLenWidth;
 | 
						|
 | 
						|
      // Check that adding the PkgLenWidth didn't trigger a domino effect,
 | 
						|
      // increasing the encoding width of the PkgLen again.
 | 
						|
      // The PkgLen is encoded on at most 4 bytes. It is possible to increase
 | 
						|
      // the PkgLen width if its encoding is on less than 3 bytes.
 | 
						|
      ReComputedPkgLenWidth = AmlComputePkgLengthWidth (Value);
 | 
						|
      if (ReComputedPkgLenWidth != NewPkgLenWidth) {
 | 
						|
        if ((ReComputedPkgLenWidth != 0)   &&
 | 
						|
            (ReComputedPkgLenWidth < 4))
 | 
						|
        {
 | 
						|
          // No need to recompute the PkgLen since a new threshold cannot
 | 
						|
          // be reached by incrementing the value by one.
 | 
						|
          Value += 1;
 | 
						|
        } else {
 | 
						|
          ASSERT (0);
 | 
						|
          return EFI_INVALID_PARAMETER;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      *Diff += (InitialPkgLenWidth > ReComputedPkgLenWidth) ?
 | 
						|
               (InitialPkgLenWidth - ReComputedPkgLenWidth) :
 | 
						|
               (ReComputedPkgLenWidth - InitialPkgLenWidth);
 | 
						|
      ObjectNode->PkgLen = Value;
 | 
						|
    } // PkgLen update.
 | 
						|
 | 
						|
    // During CodeGeneration, the tree is incomplete and
 | 
						|
    // there is no root node at the top of the tree. Stop
 | 
						|
    // propagating the new size when finding a root node
 | 
						|
    // OR when a NULL parent is found.
 | 
						|
    ParentNode = AmlGetParent ((AML_NODE_HEADER *)Node);
 | 
						|
    if (ParentNode != NULL) {
 | 
						|
      // Propagate the size up the tree.
 | 
						|
      Status = AmlPropagateSize (
 | 
						|
                 Node->Parent,
 | 
						|
                 IsIncrement,
 | 
						|
                 Diff
 | 
						|
                 );
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        ASSERT (0);
 | 
						|
        return Status;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else if (IS_AML_ROOT_NODE (Node)) {
 | 
						|
    // Update the length field in the SDT header.
 | 
						|
    Value = ((AML_ROOT_NODE *)Node)->SdtHeader->Length;
 | 
						|
 | 
						|
    // Check for an over/underflows.
 | 
						|
    if ((IsIncrement && (Value > (MAX_UINT32 - *Diff))) ||
 | 
						|
        (!IsIncrement && (Value < *Diff)))
 | 
						|
    {
 | 
						|
      ASSERT (0);
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    // Update the size.
 | 
						|
    if (IsIncrement) {
 | 
						|
      Value += *Diff;
 | 
						|
    } else {
 | 
						|
      Value -= *Diff;
 | 
						|
    }
 | 
						|
 | 
						|
    ((AML_ROOT_NODE *)Node)->SdtHeader->Length = Value;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/** Propagate the node count information up the tree.
 | 
						|
 | 
						|
  @param  [in]  ObjectNode        Pointer to an object node.
 | 
						|
  @param  [in]  IsIncrement       Choose the operation to do:
 | 
						|
                                   - TRUE:  Increment the Node's size and
 | 
						|
                                            the Node's count;
 | 
						|
                                   - FALSE: Decrement the Node's size and
 | 
						|
                                           the Node's count.
 | 
						|
  @param  [in]  NodeCount         Number of nodes added/removed (depends on the
 | 
						|
                                  value of Operation).
 | 
						|
  @param  [out] FieldWidthChange  When modifying the integer, it can be
 | 
						|
                                  promoted/demoted, e.g. from UINT8 to UINT16.
 | 
						|
                                  Stores the change in width.
 | 
						|
                                  Can be negative.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The function completed successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AmlPropagateNodeCount (
 | 
						|
  IN  AML_OBJECT_NODE  *ObjectNode,
 | 
						|
  IN  BOOLEAN          IsIncrement,
 | 
						|
  IN  UINT8            NodeCount,
 | 
						|
  OUT INT8             *FieldWidthChange
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  AML_NODE_HEADER  *NodeCountArg;
 | 
						|
  UINT8            CurrNodeCount;
 | 
						|
 | 
						|
  // Currently there is no use case where (NodeCount > 1).
 | 
						|
  if (!IS_AML_OBJECT_NODE (ObjectNode)  ||
 | 
						|
      (FieldWidthChange == NULL)        ||
 | 
						|
      (NodeCount > 1))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  *FieldWidthChange = 0;
 | 
						|
 | 
						|
  // Update the number of elements stored in PackageOp and VarPackageOp.
 | 
						|
  // The number of elements is stored as the first fixed argument.
 | 
						|
  // DefPackage := PackageOp PkgLength NumElements PackageElementList
 | 
						|
  // PackageOp := 0x12
 | 
						|
  // DefVarPackage := VarPackageOp PkgLength VarNumElements PackageElementList
 | 
						|
  // VarPackageOp := 0x13
 | 
						|
  // NumElements := ByteData
 | 
						|
  // VarNumElements := TermArg => Integer
 | 
						|
  NodeCountArg = AmlGetFixedArgument (ObjectNode, EAmlParseIndexTerm0);
 | 
						|
  if (AmlNodeCompareOpCode (ObjectNode, AML_PACKAGE_OP, 0)) {
 | 
						|
    // First fixed argument of PackageOp stores the number of elements
 | 
						|
    // in the package. It is an UINT8.
 | 
						|
 | 
						|
    // Check for over/underflow.
 | 
						|
    CurrNodeCount = *(((AML_DATA_NODE *)NodeCountArg)->Buffer);
 | 
						|
    if ((IsIncrement && (CurrNodeCount == MAX_UINT8)) ||
 | 
						|
        (!IsIncrement && (CurrNodeCount == 0)))
 | 
						|
    {
 | 
						|
      ASSERT (0);
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    // Update the node count in the DataNode.
 | 
						|
    CurrNodeCount                              = IsIncrement ? (CurrNodeCount + 1) : (CurrNodeCount - 1);
 | 
						|
    *(((AML_DATA_NODE *)NodeCountArg)->Buffer) =  CurrNodeCount;
 | 
						|
  } else if (AmlNodeCompareOpCode (ObjectNode, AML_VAR_PACKAGE_OP, 0)) {
 | 
						|
    // First fixed argument of PackageOp stores the number of elements
 | 
						|
    // in the package. It is an integer (can be a BYTE, WORD, DWORD, QWORD).
 | 
						|
    Status = AmlNodeUpdateIntegerValue (
 | 
						|
               (AML_OBJECT_NODE *)NodeCountArg,
 | 
						|
               IsIncrement,
 | 
						|
               NodeCount,
 | 
						|
               FieldWidthChange
 | 
						|
               );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      ASSERT (0);
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/** Propagate information up the tree.
 | 
						|
 | 
						|
  The information can be a new size, a new number of arguments.
 | 
						|
 | 
						|
  @param  [in]  Node          Pointer to a node.
 | 
						|
                              Must be a root node or an object node.
 | 
						|
  @param  [in]  IsIncrement   Choose the operation to do:
 | 
						|
                               - TRUE:  Increment the Node's size and
 | 
						|
                                        the Node's count;
 | 
						|
                               - FALSE: Decrement the Node's size and
 | 
						|
                                        the Node's count.
 | 
						|
  @param  [in]  Diff          Value to add/subtract to the Node's size.
 | 
						|
  @param  [in]  NodeCount     Number of nodes added/removed.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The function completed successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AmlPropagateInformation (
 | 
						|
  IN  AML_NODE_HEADER  *Node,
 | 
						|
  IN  BOOLEAN          IsIncrement,
 | 
						|
  IN  UINT32           Diff,
 | 
						|
  IN  UINT8            NodeCount
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  INT8        FieldWidthChange;
 | 
						|
 | 
						|
  // Currently there is no use case where (NodeCount > 1).
 | 
						|
  if ((!IS_AML_ROOT_NODE (Node)     &&
 | 
						|
       !IS_AML_OBJECT_NODE (Node))  ||
 | 
						|
      (NodeCount > 1))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  // Propagate the node count first as it may change the number of bytes
 | 
						|
  // needed to store the node count, and then impact FieldWidthChange.
 | 
						|
  if ((NodeCount != 0) &&
 | 
						|
      IS_AML_OBJECT_NODE (Node))
 | 
						|
  {
 | 
						|
    Status = AmlPropagateNodeCount (
 | 
						|
               (AML_OBJECT_NODE *)Node,
 | 
						|
               IsIncrement,
 | 
						|
               NodeCount,
 | 
						|
               &FieldWidthChange
 | 
						|
               );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      ASSERT (0);
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
 | 
						|
    // Propagate the potential field width change.
 | 
						|
    // Maximum change is between UINT8/UINT64: 8 bytes.
 | 
						|
    if ((ABS (FieldWidthChange) > 8)                          ||
 | 
						|
        (IsIncrement                                          &&
 | 
						|
         ((FieldWidthChange < 0)                             ||
 | 
						|
          ((Diff + (UINT8)FieldWidthChange) > MAX_UINT32)))  ||
 | 
						|
        (!IsIncrement                                         &&
 | 
						|
         ((FieldWidthChange > 0)                             ||
 | 
						|
          (Diff < (UINT32)ABS (FieldWidthChange)))))
 | 
						|
    {
 | 
						|
      ASSERT (0);
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    Diff = (UINT32)(Diff + (UINT8)ABS (FieldWidthChange));
 | 
						|
  }
 | 
						|
 | 
						|
  // Diff can be zero if some data is updated without modifying the data size.
 | 
						|
  if (Diff != 0) {
 | 
						|
    Status = AmlPropagateSize (Node, IsIncrement, &Diff);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      ASSERT (0);
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/** Find and set the EndTag's Checksum of a list of Resource Data elements.
 | 
						|
 | 
						|
  Lists of Resource Data elements end with an EndTag (most of the time). This
 | 
						|
  function finds the EndTag (if present) in a list of Resource Data elements
 | 
						|
  and sets the checksum.
 | 
						|
 | 
						|
  ACPI 6.4, s6.4.2.9 "End Tag":
 | 
						|
  "This checksum is generated such that adding it to the sum of all the data
 | 
						|
  bytes will produce a zero sum."
 | 
						|
  "If the checksum field is zero, the resource data is treated as if the
 | 
						|
  checksum operation succeeded. Configuration proceeds normally."
 | 
						|
 | 
						|
  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.
 | 
						|
 | 
						|
  @param [in]  BufferOpNode   Node having a list of Resource Data elements.
 | 
						|
  @param [in]  CheckSum       CheckSum to store in the EndTag.
 | 
						|
                              To ignore/avoid computing the checksum,
 | 
						|
                              give 0.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The function completed successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Invalid parameter.
 | 
						|
  @retval EFI_NOT_FOUND           No EndTag found.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AmlSetRdListCheckSum (
 | 
						|
  IN  AML_OBJECT_NODE  *BufferOpNode,
 | 
						|
  IN  UINT8            CheckSum
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS     Status;
 | 
						|
  AML_DATA_NODE  *LastRdNode;
 | 
						|
  AML_RD_HEADER  RdDataType;
 | 
						|
 | 
						|
  if (!AmlNodeCompareOpCode (BufferOpNode, AML_BUFFER_OP, 0)) {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  // Get the last Resource data node in the variable list of
 | 
						|
  // argument of the BufferOp node.
 | 
						|
  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;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = AmlGetResourceDataType (LastRdNode, &RdDataType);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    ASSERT (0);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  // Check the LastRdNode is an EndTag.
 | 
						|
  // It is possible to have only one Resource Data in a BufferOp with
 | 
						|
  // no EndTag. Return EFI_NOT_FOUND is such case.
 | 
						|
  if (!AmlRdCompareDescId (
 | 
						|
         &RdDataType,
 | 
						|
         AML_RD_BUILD_SMALL_DESC_ID (ACPI_SMALL_END_TAG_DESCRIPTOR_NAME)
 | 
						|
         ))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = AmlRdSetEndTagChecksum (LastRdNode->Buffer, CheckSum);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 |