1 /*******************************************************************************
   2  *
   3  * Module Name: dbmethod - Debug commands for control methods
   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 "acdispat.h"
  48 #include "acnamesp.h"
  49 #include "acdebug.h"
  50 #include "acdisasm.h"
  51 #include "acparser.h"
  52 #include "acpredef.h"
  53 
  54 
  55 #ifdef ACPI_DEBUGGER
  56 
  57 #define _COMPONENT          ACPI_CA_DEBUGGER
  58         ACPI_MODULE_NAME    ("dbmethod")
  59 
  60 
  61 /*******************************************************************************
  62  *
  63  * FUNCTION:    AcpiDbSetMethodBreakpoint
  64  *
  65  * PARAMETERS:  Location            - AML offset of breakpoint
  66  *              WalkState           - Current walk info
  67  *              Op                  - Current Op (from parse walk)
  68  *
  69  * RETURN:      None
  70  *
  71  * DESCRIPTION: Set a breakpoint in a control method at the specified
  72  *              AML offset
  73  *
  74  ******************************************************************************/
  75 
  76 void
  77 AcpiDbSetMethodBreakpoint (
  78     char                    *Location,
  79     ACPI_WALK_STATE         *WalkState,
  80     ACPI_PARSE_OBJECT       *Op)
  81 {
  82     UINT32                  Address;
  83 
  84 
  85     if (!Op)
  86     {
  87         AcpiOsPrintf ("There is no method currently executing\n");
  88         return;
  89     }
  90 
  91     /* Get and verify the breakpoint address */
  92 
  93     Address = ACPI_STRTOUL (Location, NULL, 16);
  94     if (Address <= Op->Common.AmlOffset)
  95     {
  96         AcpiOsPrintf ("Breakpoint %X is beyond current address %X\n",
  97             Address, Op->Common.AmlOffset);
  98     }
  99 
 100     /* Save breakpoint in current walk */
 101 
 102     WalkState->UserBreakpoint = Address;
 103     AcpiOsPrintf ("Breakpoint set at AML offset %X\n", Address);
 104 }
 105 
 106 
 107 /*******************************************************************************
 108  *
 109  * FUNCTION:    AcpiDbSetMethodCallBreakpoint
 110  *
 111  * PARAMETERS:  Op                  - Current Op (from parse walk)
 112  *
 113  * RETURN:      None
 114  *
 115  * DESCRIPTION: Set a breakpoint in a control method at the specified
 116  *              AML offset
 117  *
 118  ******************************************************************************/
 119 
 120 void
 121 AcpiDbSetMethodCallBreakpoint (
 122     ACPI_PARSE_OBJECT       *Op)
 123 {
 124 
 125 
 126     if (!Op)
 127     {
 128         AcpiOsPrintf ("There is no method currently executing\n");
 129         return;
 130     }
 131 
 132     AcpiGbl_StepToNextCall = TRUE;
 133 }
 134 
 135 
 136 /*******************************************************************************
 137  *
 138  * FUNCTION:    AcpiDbSetMethodData
 139  *
 140  * PARAMETERS:  TypeArg         - L for local, A for argument
 141  *              IndexArg        - which one
 142  *              ValueArg        - Value to set.
 143  *
 144  * RETURN:      None
 145  *
 146  * DESCRIPTION: Set a local or argument for the running control method.
 147  *              NOTE: only object supported is Number.
 148  *
 149  ******************************************************************************/
 150 
 151 void
 152 AcpiDbSetMethodData (
 153     char                    *TypeArg,
 154     char                    *IndexArg,
 155     char                    *ValueArg)
 156 {
 157     char                    Type;
 158     UINT32                  Index;
 159     UINT32                  Value;
 160     ACPI_WALK_STATE         *WalkState;
 161     ACPI_OPERAND_OBJECT     *ObjDesc;
 162     ACPI_STATUS             Status;
 163     ACPI_NAMESPACE_NODE     *Node;
 164 
 165 
 166     /* Validate TypeArg */
 167 
 168     AcpiUtStrupr (TypeArg);
 169     Type = TypeArg[0];
 170     if ((Type != 'L') &&
 171         (Type != 'A') &&
 172         (Type != 'N'))
 173     {
 174         AcpiOsPrintf ("Invalid SET operand: %s\n", TypeArg);
 175         return;
 176     }
 177 
 178     Value = ACPI_STRTOUL (ValueArg, NULL, 16);
 179 
 180     if (Type == 'N')
 181     {
 182         Node = AcpiDbConvertToNode (IndexArg);
 183         if (Node->Type != ACPI_TYPE_INTEGER)
 184         {
 185             AcpiOsPrintf ("Can only set Integer nodes\n");
 186             return;
 187         }
 188         ObjDesc = Node->Object;
 189         ObjDesc->Integer.Value = Value;
 190         return;
 191     }
 192 
 193     /* Get the index and value */
 194 
 195     Index = ACPI_STRTOUL (IndexArg, NULL, 16);
 196 
 197     WalkState = AcpiDsGetCurrentWalkState (AcpiGbl_CurrentWalkList);
 198     if (!WalkState)
 199     {
 200         AcpiOsPrintf ("There is no method currently executing\n");
 201         return;
 202     }
 203 
 204     /* Create and initialize the new object */
 205 
 206     ObjDesc = AcpiUtCreateIntegerObject ((UINT64) Value);
 207     if (!ObjDesc)
 208     {
 209         AcpiOsPrintf ("Could not create an internal object\n");
 210         return;
 211     }
 212 
 213     /* Store the new object into the target */
 214 
 215     switch (Type)
 216     {
 217     case 'A':
 218 
 219         /* Set a method argument */
 220 
 221         if (Index > ACPI_METHOD_MAX_ARG)
 222         {
 223             AcpiOsPrintf ("Arg%u - Invalid argument name\n", Index);
 224             goto Cleanup;
 225         }
 226 
 227         Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_ARG, Index, ObjDesc,
 228                     WalkState);
 229         if (ACPI_FAILURE (Status))
 230         {
 231             goto Cleanup;
 232         }
 233 
 234         ObjDesc = WalkState->Arguments[Index].Object;
 235 
 236         AcpiOsPrintf ("Arg%u: ", Index);
 237         AcpiDmDisplayInternalObject (ObjDesc, WalkState);
 238         break;
 239 
 240     case 'L':
 241 
 242         /* Set a method local */
 243 
 244         if (Index > ACPI_METHOD_MAX_LOCAL)
 245         {
 246             AcpiOsPrintf ("Local%u - Invalid local variable name\n", Index);
 247             goto Cleanup;
 248         }
 249 
 250         Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_LOCAL, Index, ObjDesc,
 251                     WalkState);
 252         if (ACPI_FAILURE (Status))
 253         {
 254             goto Cleanup;
 255         }
 256 
 257         ObjDesc = WalkState->LocalVariables[Index].Object;
 258 
 259         AcpiOsPrintf ("Local%u: ", Index);
 260         AcpiDmDisplayInternalObject (ObjDesc, WalkState);
 261         break;
 262 
 263     default:
 264 
 265         break;
 266     }
 267 
 268 Cleanup:
 269     AcpiUtRemoveReference (ObjDesc);
 270 }
 271 
 272 
 273 /*******************************************************************************
 274  *
 275  * FUNCTION:    AcpiDbDisassembleAml
 276  *
 277  * PARAMETERS:  Statements          - Number of statements to disassemble
 278  *              Op                  - Current Op (from parse walk)
 279  *
 280  * RETURN:      None
 281  *
 282  * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number
 283  *              of statements specified.
 284  *
 285  ******************************************************************************/
 286 
 287 void
 288 AcpiDbDisassembleAml (
 289     char                    *Statements,
 290     ACPI_PARSE_OBJECT       *Op)
 291 {
 292     UINT32                  NumStatements = 8;
 293 
 294 
 295     if (!Op)
 296     {
 297         AcpiOsPrintf ("There is no method currently executing\n");
 298         return;
 299     }
 300 
 301     if (Statements)
 302     {
 303         NumStatements = ACPI_STRTOUL (Statements, NULL, 0);
 304     }
 305 
 306     AcpiDmDisassemble (NULL, Op, NumStatements);
 307 }
 308 
 309 
 310 /*******************************************************************************
 311  *
 312  * FUNCTION:    AcpiDbDisassembleMethod
 313  *
 314  * PARAMETERS:  Name            - Name of control method
 315  *
 316  * RETURN:      None
 317  *
 318  * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number
 319  *              of statements specified.
 320  *
 321  ******************************************************************************/
 322 
 323 ACPI_STATUS
 324 AcpiDbDisassembleMethod (
 325     char                    *Name)
 326 {
 327     ACPI_STATUS             Status;
 328     ACPI_PARSE_OBJECT       *Op;
 329     ACPI_WALK_STATE         *WalkState;
 330     ACPI_OPERAND_OBJECT     *ObjDesc;
 331     ACPI_NAMESPACE_NODE     *Method;
 332 
 333 
 334     Method = AcpiDbConvertToNode (Name);
 335     if (!Method)
 336     {
 337         return (AE_BAD_PARAMETER);
 338     }
 339 
 340     if (Method->Type != ACPI_TYPE_METHOD)
 341     {
 342         ACPI_ERROR ((AE_INFO, "%s (%s): Object must be a control method",
 343             Name, AcpiUtGetTypeName (Method->Type)));
 344         return (AE_BAD_PARAMETER);
 345     }
 346 
 347     ObjDesc = Method->Object;
 348 
 349     Op = AcpiPsCreateScopeOp ();
 350     if (!Op)
 351     {
 352         return (AE_NO_MEMORY);
 353     }
 354 
 355     /* Create and initialize a new walk state */
 356 
 357     WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL);
 358     if (!WalkState)
 359     {
 360         return (AE_NO_MEMORY);
 361     }
 362 
 363     Status = AcpiDsInitAmlWalk (WalkState, Op, NULL,
 364         ObjDesc->Method.AmlStart,
 365         ObjDesc->Method.AmlLength, NULL, ACPI_IMODE_LOAD_PASS1);
 366     if (ACPI_FAILURE (Status))
 367     {
 368         return (Status);
 369     }
 370 
 371     Status = AcpiUtAllocateOwnerId (&ObjDesc->Method.OwnerId);
 372     WalkState->OwnerId = ObjDesc->Method.OwnerId;
 373 
 374     /* Push start scope on scope stack and make it current */
 375 
 376     Status = AcpiDsScopeStackPush (Method,
 377         Method->Type, WalkState);
 378     if (ACPI_FAILURE (Status))
 379     {
 380         return (Status);
 381     }
 382 
 383     /* Parse the entire method AML including deferred operators */
 384 
 385     WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;
 386     WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE;
 387 
 388     Status = AcpiPsParseAml (WalkState);
 389     (void) AcpiDmParseDeferredOps (Op);
 390 
 391     /* Now we can disassemble the method */
 392 
 393     AcpiGbl_DbOpt_verbose = FALSE;
 394     AcpiDmDisassemble (NULL, Op, 0);
 395     AcpiGbl_DbOpt_verbose = TRUE;
 396 
 397     AcpiPsDeleteParseTree (Op);
 398 
 399     /* Method cleanup */
 400 
 401     AcpiNsDeleteNamespaceSubtree (Method);
 402     AcpiNsDeleteNamespaceByOwner (ObjDesc->Method.OwnerId);
 403     AcpiUtReleaseOwnerId (&ObjDesc->Method.OwnerId);
 404     return (AE_OK);
 405 }
 406 
 407 #endif /* ACPI_DEBUGGER */