dbmethod.c revision 306536
1/*******************************************************************************
2 *
3 * Module Name: dbmethod - Debug commands for control methods
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2016, 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/acparser.h>
50#include <contrib/dev/acpica/include/acpredef.h>
51
52
53#define _COMPONENT          ACPI_CA_DEBUGGER
54        ACPI_MODULE_NAME    ("dbmethod")
55
56
57/*******************************************************************************
58 *
59 * FUNCTION:    AcpiDbSetMethodBreakpoint
60 *
61 * PARAMETERS:  Location            - AML offset of breakpoint
62 *              WalkState           - Current walk info
63 *              Op                  - Current Op (from parse walk)
64 *
65 * RETURN:      None
66 *
67 * DESCRIPTION: Set a breakpoint in a control method at the specified
68 *              AML offset
69 *
70 ******************************************************************************/
71
72void
73AcpiDbSetMethodBreakpoint (
74    char                    *Location,
75    ACPI_WALK_STATE         *WalkState,
76    ACPI_PARSE_OBJECT       *Op)
77{
78    UINT32                  Address;
79    UINT32                  AmlOffset;
80
81
82    if (!Op)
83    {
84        AcpiOsPrintf ("There is no method currently executing\n");
85        return;
86    }
87
88    /* Get and verify the breakpoint address */
89
90    Address = strtoul (Location, NULL, 16);
91    AmlOffset = (UINT32) ACPI_PTR_DIFF (Op->Common.Aml,
92        WalkState->ParserState.AmlStart);
93    if (Address <= AmlOffset)
94    {
95        AcpiOsPrintf ("Breakpoint %X is beyond current address %X\n",
96            Address, 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 = 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 = 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",
228                Index);
229            goto Cleanup;
230        }
231
232        Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_ARG,
233            Index, ObjDesc, WalkState);
234        if (ACPI_FAILURE (Status))
235        {
236            goto Cleanup;
237        }
238
239        ObjDesc = WalkState->Arguments[Index].Object;
240
241        AcpiOsPrintf ("Arg%u: ", Index);
242        AcpiDbDisplayInternalObject (ObjDesc, WalkState);
243        break;
244
245    case 'L':
246
247        /* Set a method local */
248
249        if (Index > ACPI_METHOD_MAX_LOCAL)
250        {
251            AcpiOsPrintf ("Local%u - Invalid local variable name\n",
252                Index);
253            goto Cleanup;
254        }
255
256        Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_LOCAL,
257            Index, ObjDesc, WalkState);
258        if (ACPI_FAILURE (Status))
259        {
260            goto Cleanup;
261        }
262
263        ObjDesc = WalkState->LocalVariables[Index].Object;
264
265        AcpiOsPrintf ("Local%u: ", Index);
266        AcpiDbDisplayInternalObject (ObjDesc, WalkState);
267        break;
268
269    default:
270
271        break;
272    }
273
274Cleanup:
275    AcpiUtRemoveReference (ObjDesc);
276}
277
278
279/*******************************************************************************
280 *
281 * FUNCTION:    AcpiDbDisassembleAml
282 *
283 * PARAMETERS:  Statements          - Number of statements to disassemble
284 *              Op                  - Current Op (from parse walk)
285 *
286 * RETURN:      None
287 *
288 * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number
289 *              of statements specified.
290 *
291 ******************************************************************************/
292
293void
294AcpiDbDisassembleAml (
295    char                    *Statements,
296    ACPI_PARSE_OBJECT       *Op)
297{
298    UINT32                  NumStatements = 8;
299
300
301    if (!Op)
302    {
303        AcpiOsPrintf ("There is no method currently executing\n");
304        return;
305    }
306
307    if (Statements)
308    {
309        NumStatements = strtoul (Statements, NULL, 0);
310    }
311
312#ifdef ACPI_DISASSEMBLER
313    AcpiDmDisassemble (NULL, Op, NumStatements);
314#endif
315}
316
317
318/*******************************************************************************
319 *
320 * FUNCTION:    AcpiDbDisassembleMethod
321 *
322 * PARAMETERS:  Name            - Name of control method
323 *
324 * RETURN:      None
325 *
326 * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number
327 *              of statements specified.
328 *
329 ******************************************************************************/
330
331ACPI_STATUS
332AcpiDbDisassembleMethod (
333    char                    *Name)
334{
335    ACPI_STATUS             Status;
336    ACPI_PARSE_OBJECT       *Op;
337    ACPI_WALK_STATE         *WalkState;
338    ACPI_OPERAND_OBJECT     *ObjDesc;
339    ACPI_NAMESPACE_NODE     *Method;
340
341
342    Method = AcpiDbConvertToNode (Name);
343    if (!Method)
344    {
345        return (AE_BAD_PARAMETER);
346    }
347
348    if (Method->Type != ACPI_TYPE_METHOD)
349    {
350        ACPI_ERROR ((AE_INFO, "%s (%s): Object must be a control method",
351            Name, AcpiUtGetTypeName (Method->Type)));
352        return (AE_BAD_PARAMETER);
353    }
354
355    ObjDesc = Method->Object;
356
357    Op = AcpiPsCreateScopeOp (ObjDesc->Method.AmlStart);
358    if (!Op)
359    {
360        return (AE_NO_MEMORY);
361    }
362
363    /* Create and initialize a new walk state */
364
365    WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL);
366    if (!WalkState)
367    {
368        return (AE_NO_MEMORY);
369    }
370
371    Status = AcpiDsInitAmlWalk (WalkState, Op, NULL,
372        ObjDesc->Method.AmlStart,
373        ObjDesc->Method.AmlLength, NULL, ACPI_IMODE_LOAD_PASS1);
374    if (ACPI_FAILURE (Status))
375    {
376        return (Status);
377    }
378
379    Status = AcpiUtAllocateOwnerId (&ObjDesc->Method.OwnerId);
380    WalkState->OwnerId = ObjDesc->Method.OwnerId;
381
382    /* Push start scope on scope stack and make it current */
383
384    Status = AcpiDsScopeStackPush (Method,
385        Method->Type, WalkState);
386    if (ACPI_FAILURE (Status))
387    {
388        return (Status);
389    }
390
391    /* Parse the entire method AML including deferred operators */
392
393    WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;
394    WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE;
395
396    Status = AcpiPsParseAml (WalkState);
397
398#ifdef ACPI_DISASSEMBLER
399    (void) AcpiDmParseDeferredOps (Op);
400
401    /* Now we can disassemble the method */
402
403    AcpiGbl_DmOpt_Verbose = FALSE;
404    AcpiDmDisassemble (NULL, Op, 0);
405    AcpiGbl_DmOpt_Verbose = TRUE;
406#endif
407
408    AcpiPsDeleteParseTree (Op);
409
410    /* Method cleanup */
411
412    AcpiNsDeleteNamespaceSubtree (Method);
413    AcpiNsDeleteNamespaceByOwner (ObjDesc->Method.OwnerId);
414    AcpiUtReleaseOwnerId (&ObjDesc->Method.OwnerId);
415    return (AE_OK);
416}
417