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>
		
			
				
	
	
		
			348 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			348 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  AML Resource Data Parser.
 | 
						|
 | 
						|
  Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
 | 
						|
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
  @par Glossary:
 | 
						|
  - Rd or RD   - Resource Data
 | 
						|
  - Rds or RDS - Resource Data Small
 | 
						|
  - Rdl or RDL - Resource Data Large
 | 
						|
**/
 | 
						|
 | 
						|
#include <Parser/AmlResourceDataParser.h>
 | 
						|
 | 
						|
#include <AmlCoreInterface.h>
 | 
						|
#include <AmlDbgPrint/AmlDbgPrint.h>
 | 
						|
#include <Tree/AmlNode.h>
 | 
						|
#include <Tree/AmlTree.h>
 | 
						|
 | 
						|
/** Get the size of a resource data element using a stream.
 | 
						|
 | 
						|
  If the resource data element is of the large type, the Header
 | 
						|
  is expected to be at least 3 bytes long.
 | 
						|
 | 
						|
  The use of a stream makes this function safer
 | 
						|
  than the version without stream.
 | 
						|
 | 
						|
  @param  [in]  FStream     Forward stream pointing to a resource data
 | 
						|
                            element.
 | 
						|
                            The stream must not be at its end.
 | 
						|
 | 
						|
  @return The size of the resource data element.
 | 
						|
          Zero if error.
 | 
						|
**/
 | 
						|
UINT32
 | 
						|
EFIAPI
 | 
						|
AmlRdStreamGetRdSize (
 | 
						|
  IN  CONST AML_STREAM  *FStream
 | 
						|
  )
 | 
						|
{
 | 
						|
  CONST AML_RD_HEADER  *CurrRdElement;
 | 
						|
 | 
						|
  if (!IS_STREAM (FStream)        ||
 | 
						|
      IS_END_OF_STREAM (FStream)  ||
 | 
						|
      !IS_STREAM_FORWARD (FStream))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  CurrRdElement = (CONST AML_RD_HEADER *)AmlStreamGetCurrPos (FStream);
 | 
						|
  if (CurrRdElement == NULL) {
 | 
						|
    ASSERT (0);
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  // If the resource data element is of the large type, check for overflow.
 | 
						|
  if (AML_RD_IS_LARGE (CurrRdElement) &&
 | 
						|
      (AmlStreamGetFreeSpace (FStream) <
 | 
						|
       sizeof (ACPI_LARGE_RESOURCE_HEADER)))
 | 
						|
  {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  return AmlRdGetSize (CurrRdElement);
 | 
						|
}
 | 
						|
 | 
						|
/** Check the nesting of resource data elements that are dependent
 | 
						|
    function descriptors.
 | 
						|
 | 
						|
  @param  [in]  FStream             Forward stream pointing to a resource data
 | 
						|
                                    element. The stream is not
 | 
						|
                                    modified/progressing.
 | 
						|
                                    The stream must not be at its end.
 | 
						|
  @param  [in, out] InFunctionDesc  Pointer holding the nesting of the
 | 
						|
                                    resource data buffer.
 | 
						|
                                    InFunctionDesc holds TRUE if the resource
 | 
						|
                                    data at the address of Buffer is currently
 | 
						|
                                    in a dependent function descriptor list.
 | 
						|
 | 
						|
  @retval FALSE   The Header being parsed is ending a function descriptor
 | 
						|
                  list when none started. This should not be possible for a
 | 
						|
                  resource data buffer.
 | 
						|
  @retval TRUE    Otherwise.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
BOOLEAN
 | 
						|
EFIAPI
 | 
						|
AmlRdCheckFunctionDescNesting (
 | 
						|
  IN      CONST AML_STREAM  *FStream,
 | 
						|
  IN  OUT       BOOLEAN     *InFunctionDesc
 | 
						|
  )
 | 
						|
{
 | 
						|
  CONST AML_RD_HEADER  *CurrRdElement;
 | 
						|
 | 
						|
  if (!IS_STREAM (FStream)        ||
 | 
						|
      IS_END_OF_STREAM (FStream)  ||
 | 
						|
      (InFunctionDesc == NULL))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  CurrRdElement = AmlStreamGetCurrPos (FStream);
 | 
						|
  if (CurrRdElement == NULL) {
 | 
						|
    ASSERT (0);
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  // Starting a dependent function descriptor.
 | 
						|
  // It is possible to start one when one has already started.
 | 
						|
  if (AmlRdCompareDescId (
 | 
						|
        CurrRdElement,
 | 
						|
        AML_RD_BUILD_SMALL_DESC_ID (
 | 
						|
          ACPI_SMALL_START_DEPENDENT_DESCRIPTOR_NAME
 | 
						|
          )
 | 
						|
        ))
 | 
						|
  {
 | 
						|
    *InFunctionDesc = TRUE;
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  // Ending a dependent function descriptor.
 | 
						|
  if (AmlRdCompareDescId (
 | 
						|
        CurrRdElement,
 | 
						|
        AML_RD_BUILD_SMALL_DESC_ID (
 | 
						|
          ACPI_SMALL_END_DEPENDENT_DESCRIPTOR_NAME
 | 
						|
          )
 | 
						|
        ))
 | 
						|
  {
 | 
						|
    if (*InFunctionDesc) {
 | 
						|
      *InFunctionDesc = FALSE;
 | 
						|
      return TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
    // It should not be possible to end a dependent function descriptor
 | 
						|
    // when none started.
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/** Check whether the input stream is pointing to a valid list
 | 
						|
    of resource data elements.
 | 
						|
 | 
						|
  The check is based on the size of resource data elements.
 | 
						|
  This means that a buffer can pass this check with non-existing descriptor Ids
 | 
						|
  that have a correct size.
 | 
						|
 | 
						|
  A list of resource data elements can contain one unique resource data
 | 
						|
  element, without an end tag resource data. This is the case for
 | 
						|
  a FieldList.
 | 
						|
 | 
						|
  @param  [in]  FStream   Forward stream ideally pointing to a resource
 | 
						|
                          data element. The stream is not
 | 
						|
                          modified/progressing.
 | 
						|
                          The stream must not be at its end.
 | 
						|
 | 
						|
  @retval TRUE    The buffer is holding a valid list of resource data elements.
 | 
						|
  @retval FALSE   Otherwise.
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
EFIAPI
 | 
						|
AmlRdIsResourceDataBuffer (
 | 
						|
  IN  CONST AML_STREAM  *FStream
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS           Status;
 | 
						|
  UINT32               FreeSpace;
 | 
						|
  AML_STREAM           SubStream;
 | 
						|
  CONST AML_RD_HEADER  *CurrRdElement;
 | 
						|
  UINT32               CurrRdElementSize;
 | 
						|
  BOOLEAN              InFunctionDesc;
 | 
						|
 | 
						|
  if (!IS_STREAM (FStream)        ||
 | 
						|
      IS_END_OF_STREAM (FStream)  ||
 | 
						|
      !IS_STREAM_FORWARD (FStream))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  // Create a sub-stream from the input stream to leave it untouched.
 | 
						|
  Status = AmlStreamInitSubStream (FStream, &SubStream);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    ASSERT (0);
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  CurrRdElement = AmlStreamGetCurrPos (&SubStream);
 | 
						|
  if (CurrRdElement == NULL) {
 | 
						|
    ASSERT (0);
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  // The first element cannot be an end tag.
 | 
						|
  if (AmlRdCompareDescId (
 | 
						|
        CurrRdElement,
 | 
						|
        AML_RD_BUILD_SMALL_DESC_ID (ACPI_SMALL_END_TAG_DESCRIPTOR_NAME)
 | 
						|
        ))
 | 
						|
  {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  InFunctionDesc = FALSE;
 | 
						|
  while (TRUE) {
 | 
						|
    FreeSpace         = AmlStreamGetFreeSpace (&SubStream);
 | 
						|
    CurrRdElement     = AmlStreamGetCurrPos (&SubStream);
 | 
						|
    CurrRdElementSize = AmlRdStreamGetRdSize (&SubStream);
 | 
						|
    if ((FreeSpace == 0)          ||
 | 
						|
        (CurrRdElement == NULL)   ||
 | 
						|
        (CurrRdElementSize == 0))
 | 
						|
    {
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!AmlRdCheckFunctionDescNesting (&SubStream, &InFunctionDesc)) {
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    if (CurrRdElementSize > FreeSpace) {
 | 
						|
      return FALSE;
 | 
						|
    } else if (CurrRdElementSize == FreeSpace) {
 | 
						|
      return TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
    // @todo Might want to check the CRC when available.
 | 
						|
    // An end tag resource data element must be the last element of the list.
 | 
						|
    // Thus the function should have already returned.
 | 
						|
    if (AmlRdCompareDescId (
 | 
						|
          CurrRdElement,
 | 
						|
          AML_RD_BUILD_SMALL_DESC_ID (ACPI_SMALL_END_TAG_DESCRIPTOR_NAME)
 | 
						|
          ))
 | 
						|
    {
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = AmlStreamProgress (&SubStream, CurrRdElementSize);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      ASSERT (0);
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
  } // while
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/** Parse a ResourceDataBuffer.
 | 
						|
 | 
						|
  For each resource data element, create a data node
 | 
						|
  and add them to the variable list of arguments of the BufferNode.
 | 
						|
 | 
						|
  The input stream is expected to point to a valid list of resource data
 | 
						|
  elements. A function is available to check it for the caller.
 | 
						|
 | 
						|
  @param  [in]  BufferNode    Buffer node.
 | 
						|
  @param  [in]  FStream       Forward stream pointing to a resource data
 | 
						|
                              element.
 | 
						|
                              The stream must not be at its end.
 | 
						|
 | 
						|
  @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
 | 
						|
AmlParseResourceData (
 | 
						|
  IN  AML_OBJECT_NODE  *BufferNode,
 | 
						|
  IN  AML_STREAM       *FStream
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS           Status;
 | 
						|
  AML_DATA_NODE        *NewNode;
 | 
						|
  UINT32               FreeSpace;
 | 
						|
  CONST AML_RD_HEADER  *CurrRdElement;
 | 
						|
  UINT32               CurrRdElementSize;
 | 
						|
 | 
						|
  // Check that BufferNode is an ObjectNode and has a ByteList.
 | 
						|
  if (!AmlNodeHasAttribute (BufferNode, AML_HAS_BYTE_LIST)  ||
 | 
						|
      !IS_STREAM (FStream)                                  ||
 | 
						|
      IS_END_OF_STREAM (FStream)                            ||
 | 
						|
      !IS_STREAM_FORWARD (FStream))
 | 
						|
  {
 | 
						|
    ASSERT (0);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  // Iterate through the resource data elements and create nodes.
 | 
						|
  // We assume the Buffer has already been validated as a list of
 | 
						|
  // resource data elements, so less checks are made.
 | 
						|
  while (TRUE) {
 | 
						|
    FreeSpace = AmlStreamGetFreeSpace (FStream);
 | 
						|
    if (FreeSpace == 0) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    CurrRdElement     = (CONST AML_RD_HEADER *)AmlStreamGetCurrPos (FStream);
 | 
						|
    CurrRdElementSize = AmlRdStreamGetRdSize (FStream);
 | 
						|
 | 
						|
    Status = AmlCreateDataNode (
 | 
						|
               EAmlNodeDataTypeResourceData,
 | 
						|
               (CONST UINT8 *)CurrRdElement,
 | 
						|
               CurrRdElementSize,
 | 
						|
               &NewNode
 | 
						|
               );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      ASSERT (0);
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = AmlVarListAddTailInternal (
 | 
						|
               (AML_NODE_HEADER *)BufferNode,
 | 
						|
               (AML_NODE_HEADER *)NewNode
 | 
						|
               );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      ASSERT (0);
 | 
						|
      AmlDeleteTree ((AML_NODE_HEADER *)NewNode);
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = AmlStreamProgress (FStream, CurrRdElementSize);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      ASSERT (0);
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
 | 
						|
    AMLDBG_DUMP_RAW (CurrRdElement, CurrRdElementSize);
 | 
						|
 | 
						|
    // Exit the loop when finding the resource data end tag.
 | 
						|
    if (AmlRdCompareDescId (
 | 
						|
          CurrRdElement,
 | 
						|
          AML_RD_BUILD_SMALL_DESC_ID (ACPI_SMALL_END_TAG_DESCRIPTOR_NAME)
 | 
						|
          ))
 | 
						|
    {
 | 
						|
      if (FreeSpace != CurrRdElementSize) {
 | 
						|
        ASSERT (0);
 | 
						|
        return EFI_INVALID_PARAMETER;
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  } // while
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 |