1 /*******************************************************************************
   2  *
   3  * Module Name: dmobject - ACPI object decode and display
   4  *
   5  ******************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, Intel Corp.
   9  * All rights reserved.
  10  *
  11  * Redistribution and use in source and binary forms, with or without
  12  * modification, are permitted provided that the following conditions
  13  * are met:
  14  * 1. Redistributions of source code must retain the above copyright
  15  *    notice, this list of conditions, and the following disclaimer,
  16  *    without modification.
  17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18  *    substantially similar to the "NO WARRANTY" disclaimer below
  19  *    ("Disclaimer") and any redistribution must be conditioned upon
  20  *    including a substantially similar Disclaimer requirement for further
  21  *    binary redistribution.
  22  * 3. Neither the names of the above-listed copyright holders nor the names
  23  *    of any contributors may be used to endorse or promote products derived
  24  *    from this software without specific prior written permission.
  25  *
  26  * Alternatively, this software may be distributed under the terms of the
  27  * GNU General Public License ("GPL") version 2 as published by the Free
  28  * Software Foundation.
  29  *
  30  * NO WARRANTY
  31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41  * POSSIBILITY OF SUCH DAMAGES.
  42  */
  43 
  44 
  45 #include "acpi.h"
  46 #include "accommon.h"
  47 #include "acnamesp.h"
  48 #include "acdisasm.h"
  49 
  50 
  51 #ifdef ACPI_DISASSEMBLER
  52 
  53 #define _COMPONENT          ACPI_CA_DEBUGGER
  54         ACPI_MODULE_NAME    ("dmnames")
  55 
  56 /* Local prototypes */
  57 
  58 static void
  59 AcpiDmDecodeNode (
  60     ACPI_NAMESPACE_NODE     *Node);
  61 
  62 
  63 /*******************************************************************************
  64  *
  65  * FUNCTION:    AcpiDmDumpMethodInfo
  66  *
  67  * PARAMETERS:  Status          - Method execution status
  68  *              WalkState       - Current state of the parse tree walk
  69  *              Op              - Executing parse op
  70  *
  71  * RETURN:      None
  72  *
  73  * DESCRIPTION: Called when a method has been aborted because of an error.
  74  *              Dumps the method execution stack, and the method locals/args,
  75  *              and disassembles the AML opcode that failed.
  76  *
  77  ******************************************************************************/
  78 
  79 void
  80 AcpiDmDumpMethodInfo (
  81     ACPI_STATUS             Status,
  82     ACPI_WALK_STATE         *WalkState,
  83     ACPI_PARSE_OBJECT       *Op)
  84 {
  85     ACPI_PARSE_OBJECT       *Next;
  86     ACPI_THREAD_STATE       *Thread;
  87     ACPI_WALK_STATE         *NextWalkState;
  88     ACPI_NAMESPACE_NODE     *PreviousMethod = NULL;
  89 
  90 
  91     /* Ignore control codes, they are not errors */
  92 
  93     if ((Status & AE_CODE_MASK) == AE_CODE_CONTROL)
  94     {
  95         return;
  96     }
  97 
  98     /* We may be executing a deferred opcode */
  99 
 100     if (WalkState->DeferredNode)
 101     {
 102         AcpiOsPrintf ("Executing subtree for Buffer/Package/Region\n");
 103         return;
 104     }
 105 
 106     /*
 107      * If there is no Thread, we are not actually executing a method.
 108      * This can happen when the iASL compiler calls the interpreter
 109      * to perform constant folding.
 110      */
 111     Thread = WalkState->Thread;
 112     if (!Thread)
 113     {
 114         return;
 115     }
 116 
 117     /* Display exception and method name */
 118 
 119     AcpiOsPrintf ("\n**** Exception %s during execution of method ",
 120         AcpiFormatException (Status));
 121     AcpiNsPrintNodePathname (WalkState->MethodNode, NULL);
 122 
 123     /* Display stack of executing methods */
 124 
 125     AcpiOsPrintf ("\n\nMethod Execution Stack:\n");
 126     NextWalkState = Thread->WalkStateList;
 127 
 128     /* Walk list of linked walk states */
 129 
 130     while (NextWalkState)
 131     {
 132         AcpiOsPrintf ("    Method [%4.4s] executing: ",
 133                 AcpiUtGetNodeName (NextWalkState->MethodNode));
 134 
 135         /* First method is the currently executing method */
 136 
 137         if (NextWalkState == WalkState)
 138         {
 139             if (Op)
 140             {
 141                 /* Display currently executing ASL statement */
 142 
 143                 Next = Op->Common.Next;
 144                 Op->Common.Next = NULL;
 145 
 146                 AcpiDmDisassemble (NextWalkState, Op, ACPI_UINT32_MAX);
 147                 Op->Common.Next = Next;
 148             }
 149         }
 150         else
 151         {
 152             /*
 153              * This method has called another method
 154              * NOTE: the method call parse subtree is already deleted at this
 155              * point, so we cannot disassemble the method invocation.
 156              */
 157             AcpiOsPrintf ("Call to method ");
 158             AcpiNsPrintNodePathname (PreviousMethod, NULL);
 159         }
 160 
 161         PreviousMethod = NextWalkState->MethodNode;
 162         NextWalkState = NextWalkState->Next;
 163         AcpiOsPrintf ("\n");
 164     }
 165 
 166     /* Display the method locals and arguments */
 167 
 168     AcpiOsPrintf ("\n");
 169     AcpiDmDisplayLocals (WalkState);
 170     AcpiOsPrintf ("\n");
 171     AcpiDmDisplayArguments (WalkState);
 172     AcpiOsPrintf ("\n");
 173 }
 174 
 175 
 176 /*******************************************************************************
 177  *
 178  * FUNCTION:    AcpiDmDecodeInternalObject
 179  *
 180  * PARAMETERS:  ObjDesc         - Object to be displayed
 181  *
 182  * RETURN:      None
 183  *
 184  * DESCRIPTION: Short display of an internal object. Numbers/Strings/Buffers.
 185  *
 186  ******************************************************************************/
 187 
 188 void
 189 AcpiDmDecodeInternalObject (
 190     ACPI_OPERAND_OBJECT     *ObjDesc)
 191 {
 192     UINT32                  i;
 193 
 194 
 195     if (!ObjDesc)
 196     {
 197         AcpiOsPrintf (" Uninitialized");
 198         return;
 199     }
 200 
 201     if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND)
 202     {
 203         AcpiOsPrintf (" %p [%s]", ObjDesc, AcpiUtGetDescriptorName (ObjDesc));
 204         return;
 205     }
 206 
 207     AcpiOsPrintf (" %s", AcpiUtGetObjectTypeName (ObjDesc));
 208 
 209     switch (ObjDesc->Common.Type)
 210     {
 211     case ACPI_TYPE_INTEGER:
 212 
 213         AcpiOsPrintf (" %8.8X%8.8X",
 214                 ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value));
 215         break;
 216 
 217     case ACPI_TYPE_STRING:
 218 
 219         AcpiOsPrintf ("(%u) \"%.24s",
 220                 ObjDesc->String.Length, ObjDesc->String.Pointer);
 221 
 222         if (ObjDesc->String.Length > 24)
 223         {
 224             AcpiOsPrintf ("...");
 225         }
 226         else
 227         {
 228             AcpiOsPrintf ("\"");
 229         }
 230         break;
 231 
 232     case ACPI_TYPE_BUFFER:
 233 
 234         AcpiOsPrintf ("(%u)", ObjDesc->Buffer.Length);
 235         for (i = 0; (i < 8) && (i < ObjDesc->Buffer.Length); i++)
 236         {
 237             AcpiOsPrintf (" %2.2X", ObjDesc->Buffer.Pointer[i]);
 238         }
 239         break;
 240 
 241     default:
 242 
 243         AcpiOsPrintf (" %p", ObjDesc);
 244         break;
 245     }
 246 }
 247 
 248 
 249 /*******************************************************************************
 250  *
 251  * FUNCTION:    AcpiDmDecodeNode
 252  *
 253  * PARAMETERS:  Node        - Object to be displayed
 254  *
 255  * RETURN:      None
 256  *
 257  * DESCRIPTION: Short display of a namespace node
 258  *
 259  ******************************************************************************/
 260 
 261 static void
 262 AcpiDmDecodeNode (
 263     ACPI_NAMESPACE_NODE     *Node)
 264 {
 265 
 266     AcpiOsPrintf ("<Node>            Name %4.4s",
 267             AcpiUtGetNodeName (Node));
 268 
 269     if (Node->Flags & ANOBJ_METHOD_ARG)
 270     {
 271         AcpiOsPrintf (" [Method Arg]");
 272     }
 273     if (Node->Flags & ANOBJ_METHOD_LOCAL)
 274     {
 275         AcpiOsPrintf (" [Method Local]");
 276     }
 277 
 278     switch (Node->Type)
 279     {
 280     /* These types have no attached object */
 281 
 282     case ACPI_TYPE_DEVICE:
 283 
 284         AcpiOsPrintf (" Device");
 285         break;
 286 
 287     case ACPI_TYPE_THERMAL:
 288 
 289         AcpiOsPrintf (" Thermal Zone");
 290         break;
 291 
 292     default:
 293 
 294         AcpiDmDecodeInternalObject (AcpiNsGetAttachedObject (Node));
 295         break;
 296     }
 297 }
 298 
 299 
 300 /*******************************************************************************
 301  *
 302  * FUNCTION:    AcpiDmDisplayInternalObject
 303  *
 304  * PARAMETERS:  ObjDesc         - Object to be displayed
 305  *              WalkState       - Current walk state
 306  *
 307  * RETURN:      None
 308  *
 309  * DESCRIPTION: Short display of an internal object
 310  *
 311  ******************************************************************************/
 312 
 313 void
 314 AcpiDmDisplayInternalObject (
 315     ACPI_OPERAND_OBJECT     *ObjDesc,
 316     ACPI_WALK_STATE         *WalkState)
 317 {
 318     UINT8                   Type;
 319 
 320 
 321     AcpiOsPrintf ("%p ", ObjDesc);
 322 
 323     if (!ObjDesc)
 324     {
 325         AcpiOsPrintf ("<Null Object>\n");
 326         return;
 327     }
 328 
 329     /* Decode the object type */
 330 
 331     switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))
 332     {
 333     case ACPI_DESC_TYPE_PARSER:
 334 
 335         AcpiOsPrintf ("<Parser>  ");
 336         break;
 337 
 338     case ACPI_DESC_TYPE_NAMED:
 339 
 340         AcpiDmDecodeNode ((ACPI_NAMESPACE_NODE *) ObjDesc);
 341         break;
 342 
 343     case ACPI_DESC_TYPE_OPERAND:
 344 
 345         Type = ObjDesc->Common.Type;
 346         if (Type > ACPI_TYPE_LOCAL_MAX)
 347         {
 348             AcpiOsPrintf (" Type %X [Invalid Type]", (UINT32) Type);
 349             return;
 350         }
 351 
 352         /* Decode the ACPI object type */
 353 
 354         switch (ObjDesc->Common.Type)
 355         {
 356         case ACPI_TYPE_LOCAL_REFERENCE:
 357 
 358             AcpiOsPrintf ("[%s] ", AcpiUtGetReferenceName (ObjDesc));
 359 
 360             /* Decode the refererence */
 361 
 362             switch (ObjDesc->Reference.Class)
 363             {
 364             case ACPI_REFCLASS_LOCAL:
 365 
 366                 AcpiOsPrintf ("%X ", ObjDesc->Reference.Value);
 367                 if (WalkState)
 368                 {
 369                     ObjDesc = WalkState->LocalVariables
 370                                 [ObjDesc->Reference.Value].Object;
 371                     AcpiOsPrintf ("%p", ObjDesc);
 372                     AcpiDmDecodeInternalObject (ObjDesc);
 373                 }
 374                 break;
 375 
 376             case ACPI_REFCLASS_ARG:
 377 
 378                 AcpiOsPrintf ("%X ", ObjDesc->Reference.Value);
 379                 if (WalkState)
 380                 {
 381                     ObjDesc = WalkState->Arguments
 382                                 [ObjDesc->Reference.Value].Object;
 383                     AcpiOsPrintf ("%p", ObjDesc);
 384                     AcpiDmDecodeInternalObject (ObjDesc);
 385                 }
 386                 break;
 387 
 388             case ACPI_REFCLASS_INDEX:
 389 
 390                 switch (ObjDesc->Reference.TargetType)
 391                 {
 392                 case ACPI_TYPE_BUFFER_FIELD:
 393 
 394                     AcpiOsPrintf ("%p", ObjDesc->Reference.Object);
 395                     AcpiDmDecodeInternalObject (ObjDesc->Reference.Object);
 396                     break;
 397 
 398                 case ACPI_TYPE_PACKAGE:
 399 
 400                     AcpiOsPrintf ("%p", ObjDesc->Reference.Where);
 401                     if (!ObjDesc->Reference.Where)
 402                     {
 403                         AcpiOsPrintf (" Uninitialized WHERE pointer");
 404                     }
 405                     else
 406                     {
 407                         AcpiDmDecodeInternalObject (
 408                             *(ObjDesc->Reference.Where));
 409                     }
 410                     break;
 411 
 412                 default:
 413 
 414                     AcpiOsPrintf ("Unknown index target type");
 415                     break;
 416                 }
 417                 break;
 418 
 419             case ACPI_REFCLASS_REFOF:
 420 
 421                 if (!ObjDesc->Reference.Object)
 422                 {
 423                     AcpiOsPrintf ("Uninitialized reference subobject pointer");
 424                     break;
 425                 }
 426 
 427                 /* Reference can be to a Node or an Operand object */
 428 
 429                 switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc->Reference.Object))
 430                 {
 431                 case ACPI_DESC_TYPE_NAMED:
 432                     AcpiDmDecodeNode (ObjDesc->Reference.Object);
 433                     break;
 434 
 435                 case ACPI_DESC_TYPE_OPERAND:
 436                     AcpiDmDecodeInternalObject (ObjDesc->Reference.Object);
 437                     break;
 438 
 439                 default:
 440                     break;
 441                 }
 442                 break;
 443 
 444             case ACPI_REFCLASS_NAME:
 445 
 446                 AcpiDmDecodeNode (ObjDesc->Reference.Node);
 447                 break;
 448 
 449             case ACPI_REFCLASS_DEBUG:
 450             case ACPI_REFCLASS_TABLE:
 451 
 452                 AcpiOsPrintf ("\n");
 453                 break;
 454 
 455             default:    /* Unknown reference class */
 456 
 457                 AcpiOsPrintf ("%2.2X\n", ObjDesc->Reference.Class);
 458                 break;
 459             }
 460             break;
 461 
 462         default:
 463 
 464             AcpiOsPrintf ("<Obj>            ");
 465             AcpiDmDecodeInternalObject (ObjDesc);
 466             break;
 467         }
 468         break;
 469 
 470     default:
 471 
 472         AcpiOsPrintf ("<Not a valid ACPI Object Descriptor> [%s]",
 473             AcpiUtGetDescriptorName (ObjDesc));
 474         break;
 475     }
 476 
 477     AcpiOsPrintf ("\n");
 478 }
 479 
 480 
 481 /*******************************************************************************
 482  *
 483  * FUNCTION:    AcpiDmDisplayLocals
 484  *
 485  * PARAMETERS:  WalkState       - State for current method
 486  *
 487  * RETURN:      None
 488  *
 489  * DESCRIPTION: Display all locals for the currently running control method
 490  *
 491  ******************************************************************************/
 492 
 493 void
 494 AcpiDmDisplayLocals (
 495     ACPI_WALK_STATE         *WalkState)
 496 {
 497     UINT32                  i;
 498     ACPI_OPERAND_OBJECT     *ObjDesc;
 499     ACPI_NAMESPACE_NODE     *Node;
 500 
 501 
 502     ObjDesc = WalkState->MethodDesc;
 503     Node    = WalkState->MethodNode;
 504     if (!Node)
 505     {
 506         AcpiOsPrintf (
 507             "No method node (Executing subtree for buffer or opregion)\n");
 508         return;
 509     }
 510 
 511     if (Node->Type != ACPI_TYPE_METHOD)
 512     {
 513         AcpiOsPrintf ("Executing subtree for Buffer/Package/Region\n");
 514         return;
 515     }
 516 
 517     AcpiOsPrintf ("Local Variables for method [%4.4s]:\n",
 518             AcpiUtGetNodeName (Node));
 519 
 520     for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++)
 521     {
 522         ObjDesc = WalkState->LocalVariables[i].Object;
 523         AcpiOsPrintf ("    Local%X: ", i);
 524         AcpiDmDisplayInternalObject (ObjDesc, WalkState);
 525     }
 526 }
 527 
 528 
 529 /*******************************************************************************
 530  *
 531  * FUNCTION:    AcpiDmDisplayArguments
 532  *
 533  * PARAMETERS:  WalkState       - State for current method
 534  *
 535  * RETURN:      None
 536  *
 537  * DESCRIPTION: Display all arguments for the currently running control method
 538  *
 539  ******************************************************************************/
 540 
 541 void
 542 AcpiDmDisplayArguments (
 543     ACPI_WALK_STATE         *WalkState)
 544 {
 545     UINT32                  i;
 546     ACPI_OPERAND_OBJECT     *ObjDesc;
 547     ACPI_NAMESPACE_NODE     *Node;
 548 
 549 
 550     ObjDesc = WalkState->MethodDesc;
 551     Node    = WalkState->MethodNode;
 552     if (!Node)
 553     {
 554         AcpiOsPrintf (
 555             "No method node (Executing subtree for buffer or opregion)\n");
 556         return;
 557     }
 558 
 559     if (Node->Type != ACPI_TYPE_METHOD)
 560     {
 561         AcpiOsPrintf ("Executing subtree for Buffer/Package/Region\n");
 562         return;
 563     }
 564 
 565     AcpiOsPrintf (
 566         "Arguments for Method [%4.4s]:  (%X arguments defined, max concurrency = %X)\n",
 567         AcpiUtGetNodeName (Node), ObjDesc->Method.ParamCount, ObjDesc->Method.SyncLevel);
 568 
 569     for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++)
 570     {
 571         ObjDesc = WalkState->Arguments[i].Object;
 572         AcpiOsPrintf ("    Arg%u:   ", i);
 573         AcpiDmDisplayInternalObject (ObjDesc, WalkState);
 574     }
 575 }
 576 
 577 #endif