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