c658d6ade87a374ffa18bb3e70332347aa1330e9
[dragonfly.git] / sys / contrib / dev / acpica / source / components / debugger / dbmethod.c
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 #include "acdisasm.h"
50 #include "acparser.h"
51 #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
75 void
76 AcpiDbSetMethodBreakpoint (
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
119 void
120 AcpiDbSetMethodCallBreakpoint (
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
150 void
151 AcpiDbSetMethodData (
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
272 Cleanup:
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
291 void
292 AcpiDbDisassembleAml (
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     AcpiDmDisassemble (NULL, Op, NumStatements);
311 }
312
313
314 /*******************************************************************************
315  *
316  * FUNCTION:    AcpiDbDisassembleMethod
317  *
318  * PARAMETERS:  Name            - Name of control method
319  *
320  * RETURN:      None
321  *
322  * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number
323  *              of statements specified.
324  *
325  ******************************************************************************/
326
327 ACPI_STATUS
328 AcpiDbDisassembleMethod (
329     char                    *Name)
330 {
331     ACPI_STATUS             Status;
332     ACPI_PARSE_OBJECT       *Op;
333     ACPI_WALK_STATE         *WalkState;
334     ACPI_OPERAND_OBJECT     *ObjDesc;
335     ACPI_NAMESPACE_NODE     *Method;
336
337
338     Method = AcpiDbConvertToNode (Name);
339     if (!Method)
340     {
341         return (AE_BAD_PARAMETER);
342     }
343
344     if (Method->Type != ACPI_TYPE_METHOD)
345     {
346         ACPI_ERROR ((AE_INFO, "%s (%s): Object must be a control method",
347             Name, AcpiUtGetTypeName (Method->Type)));
348         return (AE_BAD_PARAMETER);
349     }
350
351     ObjDesc = Method->Object;
352
353     Op = AcpiPsCreateScopeOp ();
354     if (!Op)
355     {
356         return (AE_NO_MEMORY);
357     }
358
359     /* Create and initialize a new walk state */
360
361     WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL);
362     if (!WalkState)
363     {
364         return (AE_NO_MEMORY);
365     }
366
367     Status = AcpiDsInitAmlWalk (WalkState, Op, NULL,
368         ObjDesc->Method.AmlStart,
369         ObjDesc->Method.AmlLength, NULL, ACPI_IMODE_LOAD_PASS1);
370     if (ACPI_FAILURE (Status))
371     {
372         return (Status);
373     }
374
375     Status = AcpiUtAllocateOwnerId (&ObjDesc->Method.OwnerId);
376     WalkState->OwnerId = ObjDesc->Method.OwnerId;
377
378     /* Push start scope on scope stack and make it current */
379
380     Status = AcpiDsScopeStackPush (Method,
381         Method->Type, WalkState);
382     if (ACPI_FAILURE (Status))
383     {
384         return (Status);
385     }
386
387     /* Parse the entire method AML including deferred operators */
388
389     WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;
390     WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE;
391
392     Status = AcpiPsParseAml (WalkState);
393     (void) AcpiDmParseDeferredOps (Op);
394
395     /* Now we can disassemble the method */
396
397     AcpiGbl_DbOpt_Verbose = FALSE;
398     AcpiDmDisassemble (NULL, Op, 0);
399     AcpiGbl_DbOpt_Verbose = TRUE;
400
401     AcpiPsDeleteParseTree (Op);
402
403     /* Method cleanup */
404
405     AcpiNsDeleteNamespaceSubtree (Method);
406     AcpiNsDeleteNamespaceByOwner (ObjDesc->Method.OwnerId);
407     AcpiUtReleaseOwnerId (&ObjDesc->Method.OwnerId);
408     return (AE_OK);
409 }
410
411 #endif /* ACPI_DEBUGGER */