text: /*******************************************************************************
   *
   * Module Name: dbobject - ACPI object decode and display
   *
   ******************************************************************************/
  
  /*
   * Copyright (C) 2000 - 2016, Intel Corp.
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions, and the following disclaimer,
   *    without modification.
   * 2. Redistributions in binary form must reproduce at minimum a disclaimer
   *    substantially similar to the "NO WARRANTY" disclaimer below
   *    ("Disclaimer") and any redistribution must be conditioned upon
   *    including a substantially similar Disclaimer requirement for further
   *    binary redistribution.
   * 3. Neither the names of the above-listed copyright holders nor the names
   *    of any contributors may be used to endorse or promote products derived
   *    from this software without specific prior written permission.
   *
   * Alternatively, this software may be distributed under the terms of the
   * GNU General Public License ("GPL") version 2 as published by the Free
   * Software Foundation.
   *
   * NO WARRANTY
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
   * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   * POSSIBILITY OF SUCH DAMAGES.
   */
  
  #include <contrib/dev/acpica/include/acpi.h>
  #include <contrib/dev/acpica/include/accommon.h>
  #include <contrib/dev/acpica/include/acnamesp.h>
  #include <contrib/dev/acpica/include/acdebug.h>
  
  
  #define _COMPONENT          ACPI_CA_DEBUGGER
          ACPI_MODULE_NAME    ("dbobject")
  
  
  /* Local prototypes */
  
  static void
  AcpiDbDecodeNode (
      ACPI_NAMESPACE_NODE     *Node);
  
  
  /*******************************************************************************
   *
   * FUNCTION:    AcpiDbDumpMethodInfo
   *
   * PARAMETERS:  Status          - Method execution status
   *              WalkState       - Current state of the parse tree walk
   *
   * RETURN:      None
   *
   * DESCRIPTION: Called when a method has been aborted because of an error.
   *              Dumps the method execution stack, and the method locals/args,
   *              and disassembles the AML opcode that failed.
   *
   ******************************************************************************/
  
  void
  AcpiDbDumpMethodInfo (
      ACPI_STATUS             Status,
      ACPI_WALK_STATE         *WalkState)
  {
      ACPI_THREAD_STATE       *Thread;
  
  
      /* Ignore control codes, they are not errors */
  
      if ((Status & AE_CODE_MASK) == AE_CODE_CONTROL)
      {
          return;
      }
  
      /* We may be executing a deferred opcode */
  
      if (WalkState->DeferredNode)
      {
          AcpiOsPrintf ("Executing subtree for Buffer/Package/Region\n");
          return;
      }
  
      /*
       * If there is no Thread, we are not actually executing a method.
       * This can happen when the iASL compiler calls the interpreter
       * to perform constant folding.
       */
      Thread = WalkState->Thread;
      if (!Thread)
      {
          return;
      }
  
      /* Display the method locals and arguments */
  
      AcpiOsPrintf ("\n");
      AcpiDbDecodeLocals (WalkState);
      AcpiOsPrintf ("\n");
      AcpiDbDecodeArguments (WalkState);
      AcpiOsPrintf ("\n");
  }
  
  
  /*******************************************************************************
   *
   * FUNCTION:    AcpiDbDecodeInternalObject
   *
   * PARAMETERS:  ObjDesc         - Object to be displayed
   *
   * RETURN:      None
   *
   * DESCRIPTION: Short display of an internal object. Numbers/Strings/Buffers.
   *
   ******************************************************************************/
  
  void
  AcpiDbDecodeInternalObject (
      ACPI_OPERAND_OBJECT     *ObjDesc)
  {
      UINT32                  i;
  
  
      if (!ObjDesc)
      {
          AcpiOsPrintf (" Uninitialized");
          return;
      }
  
      if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND)
      {
          AcpiOsPrintf (" %p [%s]", ObjDesc,
              AcpiUtGetDescriptorName (ObjDesc));
          return;
      }
  
      AcpiOsPrintf (" %s", AcpiUtGetObjectTypeName (ObjDesc));
  
      switch (ObjDesc->Common.Type)
      {
      case ACPI_TYPE_INTEGER:
  
          AcpiOsPrintf (" %8.8X%8.8X",
              ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value));
          break;
  
      case ACPI_TYPE_STRING:
  
          AcpiOsPrintf ("(%u) \"%.60s",
              ObjDesc->String.Length, ObjDesc->String.Pointer);
  
          if (ObjDesc->String.Length > 60)
          {
              AcpiOsPrintf ("...");
          }
          else
          {
              AcpiOsPrintf ("\"");
          }
          break;
  
      case ACPI_TYPE_BUFFER:
  
          AcpiOsPrintf ("(%u)", ObjDesc->Buffer.Length);
          for (i = 0; (i < 8) && (i < ObjDesc->Buffer.Length); i++)
          {
              AcpiOsPrintf (" %2.2X", ObjDesc->Buffer.Pointer[i]);
          }
          break;
  
      default:
  
          AcpiOsPrintf (" %p", ObjDesc);
          break;
      }
  }
  
  
  /*******************************************************************************
   *
   * FUNCTION:    AcpiDbDecodeNode
   *
   * PARAMETERS:  Node        - Object to be displayed
   *
   * RETURN:      None
   *
   * DESCRIPTION: Short display of a namespace node
   *
   ******************************************************************************/
  
  static void
  AcpiDbDecodeNode (
      ACPI_NAMESPACE_NODE     *Node)
  {
  
      AcpiOsPrintf ("<Node>            Name %4.4s",
          AcpiUtGetNodeName (Node));
  
      if (Node->Flags & ANOBJ_METHOD_ARG)
      {
          AcpiOsPrintf (" [Method Arg]");
      }
      if (Node->Flags & ANOBJ_METHOD_LOCAL)
      {
          AcpiOsPrintf (" [Method Local]");
      }
  
      switch (Node->Type)
      {
      /* These types have no attached object */
  
      case ACPI_TYPE_DEVICE:
  
          AcpiOsPrintf (" Device");
          break;
  
      case ACPI_TYPE_THERMAL:
  
          AcpiOsPrintf (" Thermal Zone");
          break;
  
      default:
  
          AcpiDbDecodeInternalObject (AcpiNsGetAttachedObject (Node));
          break;
      }
  }
  
  
  /*******************************************************************************
   *
   * FUNCTION:    AcpiDbDisplayInternalObject
   *
   * PARAMETERS:  ObjDesc         - Object to be displayed
   *              WalkState       - Current walk state
   *
   * RETURN:      None
   *
   * DESCRIPTION: Short display of an internal object
   *
   ******************************************************************************/
  
  void
  AcpiDbDisplayInternalObject (
      ACPI_OPERAND_OBJECT     *ObjDesc,
      ACPI_WALK_STATE         *WalkState)
  {
      UINT8                   Type;
  
  
      AcpiOsPrintf ("%p ", ObjDesc);
  
      if (!ObjDesc)
      {
          AcpiOsPrintf ("<Null Object>\n");
          return;
      }
  
      /* Decode the object type */
  
      switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))
      {
      case ACPI_DESC_TYPE_PARSER:
  
          AcpiOsPrintf ("<Parser>  ");
          break;
  
      case ACPI_DESC_TYPE_NAMED:
  
          AcpiDbDecodeNode ((ACPI_NAMESPACE_NODE *) ObjDesc);
          break;
  
      case ACPI_DESC_TYPE_OPERAND:
  
          Type = ObjDesc->Common.Type;
          if (Type > ACPI_TYPE_LOCAL_MAX)
          {
              AcpiOsPrintf (" Type %X [Invalid Type]", (UINT32) Type);
              return;
          }
  
          /* Decode the ACPI object type */
  
          switch (ObjDesc->Common.Type)
          {
          case ACPI_TYPE_LOCAL_REFERENCE:
  
              AcpiOsPrintf ("[%s] ", AcpiUtGetReferenceName (ObjDesc));
  
              /* Decode the refererence */
  
              switch (ObjDesc->Reference.Class)
              {
              case ACPI_REFCLASS_LOCAL:
  
                  AcpiOsPrintf ("%X ", ObjDesc->Reference.Value);
                  if (WalkState)
                  {
                      ObjDesc = WalkState->LocalVariables
                          [ObjDesc->Reference.Value].Object;
                      AcpiOsPrintf ("%p", ObjDesc);
                      AcpiDbDecodeInternalObject (ObjDesc);
                  }
                  break;
  
              case ACPI_REFCLASS_ARG:
  
                  AcpiOsPrintf ("%X ", ObjDesc->Reference.Value);
                  if (WalkState)
                  {
                      ObjDesc = WalkState->Arguments
                          [ObjDesc->Reference.Value].Object;
                      AcpiOsPrintf ("%p", ObjDesc);
                      AcpiDbDecodeInternalObject (ObjDesc);
                  }
                  break;
  
              case ACPI_REFCLASS_INDEX:
  
                  switch (ObjDesc->Reference.TargetType)
                  {
                  case ACPI_TYPE_BUFFER_FIELD:
  
                      AcpiOsPrintf ("%p", ObjDesc->Reference.Object);
                      AcpiDbDecodeInternalObject (ObjDesc->Reference.Object);
                      break;
  
                  case ACPI_TYPE_PACKAGE:
  
                      AcpiOsPrintf ("%p", ObjDesc->Reference.Where);
                      if (!ObjDesc->Reference.Where)
                      {
                          AcpiOsPrintf (" Uninitialized WHERE pointer");
                      }
                      else
                      {
                          AcpiDbDecodeInternalObject (
                              *(ObjDesc->Reference.Where));
                      }
                      break;
  
                  default:
  
                      AcpiOsPrintf ("Unknown index target type");
                      break;
                  }
                  break;
  
              case ACPI_REFCLASS_REFOF:
  
                  if (!ObjDesc->Reference.Object)
                  {
                      AcpiOsPrintf (
                          "Uninitialized reference subobject pointer");
                      break;
                  }
  
                  /* Reference can be to a Node or an Operand object */
  
                  switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc->Reference.Object))
                  {
                  case ACPI_DESC_TYPE_NAMED:
  
                      AcpiDbDecodeNode (ObjDesc->Reference.Object);
                      break;
  
                  case ACPI_DESC_TYPE_OPERAND:
  
                      AcpiDbDecodeInternalObject (ObjDesc->Reference.Object);
                      break;
  
                  default:
                      break;
                  }
                  break;
  
              case ACPI_REFCLASS_NAME:
  
                  AcpiDbDecodeNode (ObjDesc->Reference.Node);
                  break;
  
              case ACPI_REFCLASS_DEBUG:
              case ACPI_REFCLASS_TABLE:
  
                  AcpiOsPrintf ("\n");
                  break;
  
              default:    /* Unknown reference class */
  
                  AcpiOsPrintf ("%2.2X\n", ObjDesc->Reference.Class);
                  break;
              }
              break;
  
          default:
  
              AcpiOsPrintf ("<Obj>            ");
              AcpiDbDecodeInternalObject (ObjDesc);
              break;
          }
          break;
  
      default:
  
          AcpiOsPrintf ("<Not a valid ACPI Object Descriptor> [%s]",
              AcpiUtGetDescriptorName (ObjDesc));
          break;
      }
  
      AcpiOsPrintf ("\n");
  }
  
  
  /*******************************************************************************
   *
   * FUNCTION:    AcpiDbDecodeLocals
   *
   * PARAMETERS:  WalkState       - State for current method
   *
   * RETURN:      None
   *
   * DESCRIPTION: Display all locals for the currently running control method
   *
   ******************************************************************************/
  
  void
  AcpiDbDecodeLocals (
      ACPI_WALK_STATE         *WalkState)
  {
      UINT32                  i;
      ACPI_OPERAND_OBJECT     *ObjDesc;
      ACPI_NAMESPACE_NODE     *Node;
      BOOLEAN                 DisplayLocals = FALSE;
  
  
      ObjDesc = WalkState->MethodDesc;
      Node    = WalkState->MethodNode;
  
      if (!Node)
      {
          AcpiOsPrintf (
              "No method node (Executing subtree for buffer or opregion)\n");
          return;
      }
  
      if (Node->Type != ACPI_TYPE_METHOD)
      {
          AcpiOsPrintf ("Executing subtree for Buffer/Package/Region\n");
          return;
      }
  
      /* Are any locals actually set? */
  
      for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++)
      {
          ObjDesc = WalkState->LocalVariables[i].Object;
          if (ObjDesc)
          {
              DisplayLocals = TRUE;
              break;
          }
      }
  
      /* If any are set, only display the ones that are set */
  
      if (DisplayLocals)
      {
          AcpiOsPrintf ("\nInitialized Local Variables for method [%4.4s]:\n",
              AcpiUtGetNodeName (Node));
  
          for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++)
          {
              ObjDesc = WalkState->LocalVariables[i].Object;
              if (ObjDesc)
              {
                  AcpiOsPrintf ("    Local%X: ", i);
                  AcpiDbDisplayInternalObject (ObjDesc, WalkState);
              }
          }
      }
      else
      {
          AcpiOsPrintf (
              "No Local Variables are initialized for method [%4.4s]\n",
              AcpiUtGetNodeName (Node));
      }
  }
  
  
  /*******************************************************************************
   *
   * FUNCTION:    AcpiDbDecodeArguments
   *
   * PARAMETERS:  WalkState       - State for current method
   *
   * RETURN:      None
   *
   * DESCRIPTION: Display all arguments for the currently running control method
   *
   ******************************************************************************/
  
  void
  AcpiDbDecodeArguments (
      ACPI_WALK_STATE         *WalkState)
  {
      UINT32                  i;
      ACPI_OPERAND_OBJECT     *ObjDesc;
      ACPI_NAMESPACE_NODE     *Node;
      BOOLEAN                 DisplayArgs = FALSE;
  
  
      Node = WalkState->MethodNode;
      ObjDesc = WalkState->MethodDesc;
  
      if (!Node)
      {
          AcpiOsPrintf (
              "No method node (Executing subtree for buffer or opregion)\n");
          return;
      }
  
      if (Node->Type != ACPI_TYPE_METHOD)
      {
          AcpiOsPrintf ("Executing subtree for Buffer/Package/Region\n");
          return;
      }
  
      /* Are any arguments actually set? */
  
      for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++)
      {
          ObjDesc = WalkState->Arguments[i].Object;
          if (ObjDesc)
          {
              DisplayArgs = TRUE;
              break;
          }
      }
  
      /* If any are set, only display the ones that are set */
  
      if (DisplayArgs)
      {
          AcpiOsPrintf (
              "Initialized Arguments for Method [%4.4s]:  "
              "(%X arguments defined for method invocation)\n",
              AcpiUtGetNodeName (Node), ObjDesc->Method.ParamCount);
  
          for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++)
          {
              ObjDesc = WalkState->Arguments[i].Object;
              if (ObjDesc)
              {
                  AcpiOsPrintf ("    Arg%u:   ", i);
                  AcpiDbDisplayInternalObject (ObjDesc, WalkState);
              }
          }
      }
      else
      {
          AcpiOsPrintf (
              "No Arguments are initialized for method [%4.4s]\n",
              AcpiUtGetNodeName (Node));
      }
  }
  