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