1 /*******************************************************************************
   2  *
   3  * Module Name: dmobject - ACPI object decode and display
   4  *
   5  ******************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2011, 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 
 218     case ACPI_TYPE_STRING:
 219 
 220         AcpiOsPrintf ("(%u) \"%.24s",
 221                 ObjDesc->String.Length, ObjDesc->String.Pointer);
 222 
 223         if (ObjDesc->String.Length > 24)
 224         {
 225             AcpiOsPrintf ("...");
 226         }
 227         else
 228         {
 229             AcpiOsPrintf ("\"");
 230         }
 231         break;
 232 
 233 
 234     case ACPI_TYPE_BUFFER:
 235 
 236         AcpiOsPrintf ("(%u)", ObjDesc->Buffer.Length);
 237         for (i = 0; (i < 8) && (i < ObjDesc->Buffer.Length); i++)
 238         {
 239             AcpiOsPrintf (" %2.2X", ObjDesc->Buffer.Pointer[i]);
 240         }
 241         break;
 242 
 243 
 244     default:
 245 
 246         AcpiOsPrintf (" %p", ObjDesc);
 247         break;
 248     }
 249 }
 250 
 251 
 252 /*******************************************************************************
 253  *
 254  * FUNCTION:    AcpiDmDecodeNode
 255  *
 256  * PARAMETERS:  Node        - Object to be displayed
 257  *
 258  * RETURN:      None
 259  *
 260  * DESCRIPTION: Short display of a namespace node
 261  *
 262  ******************************************************************************/
 263 
 264 static void
 265 AcpiDmDecodeNode (
 266     ACPI_NAMESPACE_NODE     *Node)
 267 {
 268 
 269     AcpiOsPrintf ("<Node>            Name %4.4s",
 270             AcpiUtGetNodeName (Node));
 271 
 272     if (Node->Flags & ANOBJ_METHOD_ARG)
 273     {
 274         AcpiOsPrintf (" [Method Arg]");
 275     }
 276     if (Node->Flags & ANOBJ_METHOD_LOCAL)
 277     {
 278         AcpiOsPrintf (" [Method Local]");
 279     }
 280 
 281     switch (Node->Type)
 282     {
 283     /* These types have no attached object */
 284 
 285     case ACPI_TYPE_DEVICE:
 286         AcpiOsPrintf (" Device");
 287         break;
 288 
 289     case ACPI_TYPE_THERMAL:
 290         AcpiOsPrintf (" Thermal Zone");
 291         break;
 292 
 293     default:
 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 
 339     case ACPI_DESC_TYPE_NAMED:
 340 
 341         AcpiDmDecodeNode ((ACPI_NAMESPACE_NODE *) ObjDesc);
 342         break;
 343 
 344 
 345     case ACPI_DESC_TYPE_OPERAND:
 346 
 347         Type = ObjDesc->Common.Type;
 348         if (Type > ACPI_TYPE_LOCAL_MAX)
 349         {
 350             AcpiOsPrintf (" Type %X [Invalid Type]", (UINT32) Type);
 351             return;
 352         }
 353 
 354         /* Decode the ACPI object type */
 355 
 356         switch (ObjDesc->Common.Type)
 357         {
 358         case ACPI_TYPE_LOCAL_REFERENCE:
 359 
 360             AcpiOsPrintf ("[%s] ", AcpiUtGetReferenceName (ObjDesc));
 361 
 362             /* Decode the refererence */
 363 
 364             switch (ObjDesc->Reference.Class)
 365             {
 366             case ACPI_REFCLASS_LOCAL:
 367 
 368                 AcpiOsPrintf ("%X ", ObjDesc->Reference.Value);
 369                 if (WalkState)
 370                 {
 371                     ObjDesc = WalkState->LocalVariables
 372                                 [ObjDesc->Reference.Value].Object;
 373                     AcpiOsPrintf ("%p", ObjDesc);
 374                     AcpiDmDecodeInternalObject (ObjDesc);
 375                 }
 376                 break;
 377 
 378 
 379             case ACPI_REFCLASS_ARG:
 380 
 381                 AcpiOsPrintf ("%X ", ObjDesc->Reference.Value);
 382                 if (WalkState)
 383                 {
 384                     ObjDesc = WalkState->Arguments
 385                                 [ObjDesc->Reference.Value].Object;
 386                     AcpiOsPrintf ("%p", ObjDesc);
 387                     AcpiDmDecodeInternalObject (ObjDesc);
 388                 }
 389                 break;
 390 
 391 
 392             case ACPI_REFCLASS_INDEX:
 393 
 394                 switch (ObjDesc->Reference.TargetType)
 395                 {
 396                 case ACPI_TYPE_BUFFER_FIELD:
 397 
 398                     AcpiOsPrintf ("%p", ObjDesc->Reference.Object);
 399                     AcpiDmDecodeInternalObject (ObjDesc->Reference.Object);
 400                     break;
 401 
 402                 case ACPI_TYPE_PACKAGE:
 403 
 404                     AcpiOsPrintf ("%p", ObjDesc->Reference.Where);
 405                     if (!ObjDesc->Reference.Where)
 406                     {
 407                         AcpiOsPrintf (" Uninitialized WHERE pointer");
 408                     }
 409                     else
 410                     {
 411                         AcpiDmDecodeInternalObject (
 412                             *(ObjDesc->Reference.Where));
 413                     }
 414                     break;
 415 
 416                 default:
 417 
 418                     AcpiOsPrintf ("Unknown index target type");
 419                     break;
 420                 }
 421                 break;
 422 
 423 
 424             case ACPI_REFCLASS_REFOF:
 425 
 426                 if (!ObjDesc->Reference.Object)
 427                 {
 428                     AcpiOsPrintf ("Uninitialized reference subobject pointer");
 429                     break;
 430                 }
 431 
 432                 /* Reference can be to a Node or an Operand object */
 433 
 434                 switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc->Reference.Object))
 435                 {
 436                 case ACPI_DESC_TYPE_NAMED:
 437                     AcpiDmDecodeNode (ObjDesc->Reference.Object);
 438                     break;
 439 
 440                 case ACPI_DESC_TYPE_OPERAND:
 441                     AcpiDmDecodeInternalObject (ObjDesc->Reference.Object);
 442                     break;
 443 
 444                 default:
 445                     break;
 446                 }
 447                 break;
 448 
 449 
 450             case ACPI_REFCLASS_NAME:
 451 
 452                 AcpiDmDecodeNode (ObjDesc->Reference.Node);
 453                 break;
 454 
 455 
 456             case ACPI_REFCLASS_DEBUG:
 457             case ACPI_REFCLASS_TABLE:
 458 
 459                 AcpiOsPrintf ("\n");
 460                 break;
 461 
 462 
 463             default:    /* Unknown reference class */
 464 
 465                 AcpiOsPrintf ("%2.2X\n", ObjDesc->Reference.Class);
 466                 break;
 467             }
 468             break;
 469 
 470 
 471         default:
 472 
 473             AcpiOsPrintf ("<Obj>            ");
 474             AcpiDmDecodeInternalObject (ObjDesc);
 475             break;
 476         }
 477         break;
 478 
 479 
 480     default:
 481 
 482         AcpiOsPrintf ("<Not a valid ACPI Object Descriptor> [%s]",
 483             AcpiUtGetDescriptorName (ObjDesc));
 484         break;
 485     }
 486 
 487     AcpiOsPrintf ("\n");
 488 }
 489 
 490 
 491 /*******************************************************************************
 492  *
 493  * FUNCTION:    AcpiDmDisplayLocals
 494  *
 495  * PARAMETERS:  WalkState       - State for current method
 496  *
 497  * RETURN:      None
 498  *
 499  * DESCRIPTION: Display all locals for the currently running control method
 500  *
 501  ******************************************************************************/
 502 
 503 void
 504 AcpiDmDisplayLocals (
 505     ACPI_WALK_STATE         *WalkState)
 506 {
 507     UINT32                  i;
 508     ACPI_OPERAND_OBJECT     *ObjDesc;
 509     ACPI_NAMESPACE_NODE     *Node;
 510 
 511 
 512     ObjDesc = WalkState->MethodDesc;
 513     Node    = WalkState->MethodNode;
 514     if (!Node)
 515     {
 516         AcpiOsPrintf (
 517             "No method node (Executing subtree for buffer or opregion)\n");
 518         return;
 519     }
 520 
 521     if (Node->Type != ACPI_TYPE_METHOD)
 522     {
 523         AcpiOsPrintf ("Executing subtree for Buffer/Package/Region\n");
 524         return;
 525     }
 526 
 527     AcpiOsPrintf ("Local Variables for method [%4.4s]:\n",
 528             AcpiUtGetNodeName (Node));
 529 
 530     for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++)
 531     {
 532         ObjDesc = WalkState->LocalVariables[i].Object;
 533         AcpiOsPrintf ("    Local%X: ", i);
 534         AcpiDmDisplayInternalObject (ObjDesc, WalkState);
 535     }
 536 }
 537 
 538 
 539 /*******************************************************************************
 540  *
 541  * FUNCTION:    AcpiDmDisplayArguments
 542  *
 543  * PARAMETERS:  WalkState       - State for current method
 544  *
 545  * RETURN:      None
 546  *
 547  * DESCRIPTION: Display all arguments for the currently running control method
 548  *
 549  ******************************************************************************/
 550 
 551 void
 552 AcpiDmDisplayArguments (
 553     ACPI_WALK_STATE         *WalkState)
 554 {
 555     UINT32                  i;
 556     ACPI_OPERAND_OBJECT     *ObjDesc;
 557     ACPI_NAMESPACE_NODE     *Node;
 558 
 559 
 560     ObjDesc = WalkState->MethodDesc;
 561     Node    = WalkState->MethodNode;
 562     if (!Node)
 563     {
 564         AcpiOsPrintf (
 565             "No method node (Executing subtree for buffer or opregion)\n");
 566         return;
 567     }
 568 
 569     if (Node->Type != ACPI_TYPE_METHOD)
 570     {
 571         AcpiOsPrintf ("Executing subtree for Buffer/Package/Region\n");
 572         return;
 573     }
 574 
 575     AcpiOsPrintf (
 576         "Arguments for Method [%4.4s]:  (%X arguments defined, max concurrency = %X)\n",
 577         AcpiUtGetNodeName (Node), ObjDesc->Method.ParamCount, ObjDesc->Method.SyncLevel);
 578 
 579     for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++)
 580     {
 581         ObjDesc = WalkState->Arguments[i].Object;
 582         AcpiOsPrintf ("    Arg%u:   ", i);
 583         AcpiDmDisplayInternalObject (ObjDesc, WalkState);
 584     }
 585 }
 586 
 587 #endif
 588 
 589