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)
184         {
185             return;
186         }
187 
188         if (Node->Type != ACPI_TYPE_INTEGER)
189         {
190             AcpiOsPrintf ("Can only set Integer nodes\n");
191             return;
192         }
193         ObjDesc = Node->Object;
194         ObjDesc->Integer.Value = Value;
195         return;
196     }
197 
198     /* Get the index and value */
199 
200     Index = ACPI_STRTOUL (IndexArg, NULL, 16);
201 
202     WalkState = AcpiDsGetCurrentWalkState (AcpiGbl_CurrentWalkList);
203     if (!WalkState)
204     {
205         AcpiOsPrintf ("There is no method currently executing\n");
206         return;
207     }
208 
209     /* Create and initialize the new object */
210 
211     ObjDesc = AcpiUtCreateIntegerObject ((UINT64) Value);
212     if (!ObjDesc)
213     {
214         AcpiOsPrintf ("Could not create an internal object\n");
215         return;
216     }
217 
218     /* Store the new object into the target */
219 
220     switch (Type)
221     {
222     case 'A':
223 
224         /* Set a method argument */
225 
226         if (Index > ACPI_METHOD_MAX_ARG)
227         {
228             AcpiOsPrintf ("Arg%u - Invalid argument name\n", Index);
229             goto Cleanup;
230         }
231 
232         Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_ARG, Index, ObjDesc,
233                     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         AcpiDmDisplayInternalObject (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", Index);
252             goto Cleanup;
253         }
254 
255         Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_LOCAL, Index, ObjDesc,
256                     WalkState);
257         if (ACPI_FAILURE (Status))
258         {
259             goto Cleanup;
260         }
261 
262         ObjDesc = WalkState->LocalVariables[Index].Object;
263 
264         AcpiOsPrintf ("Local%u: ", Index);
265         AcpiDmDisplayInternalObject (ObjDesc, WalkState);
266         break;
267 
268     default:
269 
270         break;
271     }
272 
273 Cleanup:
274     AcpiUtRemoveReference (ObjDesc);
275 }
276 
277 
278 /*******************************************************************************
279  *
280  * FUNCTION:    AcpiDbDisassembleAml
281  *
282  * PARAMETERS:  Statements          - Number of statements to disassemble
283  *              Op                  - Current Op (from parse walk)
284  *
285  * RETURN:      None
286  *
287  * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number
288  *              of statements specified.
289  *
290  ******************************************************************************/
291 
292 void
293 AcpiDbDisassembleAml (
294     char                    *Statements,
295     ACPI_PARSE_OBJECT       *Op)
296 {
297     UINT32                  NumStatements = 8;
298 
299 
300     if (!Op)
301     {
302         AcpiOsPrintf ("There is no method currently executing\n");
303         return;
304     }
305 
306     if (Statements)
307     {
308         NumStatements = ACPI_STRTOUL (Statements, NULL, 0);
309     }
310 
311     AcpiDmDisassemble (NULL, Op, NumStatements);
312 }
313 
314 
315 /*******************************************************************************
316  *
317  * FUNCTION:    AcpiDbDisassembleMethod
318  *
319  * PARAMETERS:  Name            - Name of control method
320  *
321  * RETURN:      None
322  *
323  * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number
324  *              of statements specified.
325  *
326  ******************************************************************************/
327 
328 ACPI_STATUS
329 AcpiDbDisassembleMethod (
330     char                    *Name)
331 {
332     ACPI_STATUS             Status;
333     ACPI_PARSE_OBJECT       *Op;
334     ACPI_WALK_STATE         *WalkState;
335     ACPI_OPERAND_OBJECT     *ObjDesc;
336     ACPI_NAMESPACE_NODE     *Method;
337 
338 
339     Method = AcpiDbConvertToNode (Name);
340     if (!Method)
341     {
342         return (AE_BAD_PARAMETER);
343     }
344 
345     if (Method->Type != ACPI_TYPE_METHOD)
346     {
347         ACPI_ERROR ((AE_INFO, "%s (%s): Object must be a control method",
348             Name, AcpiUtGetTypeName (Method->Type)));
349         return (AE_BAD_PARAMETER);
350     }
351 
352     ObjDesc = Method->Object;
353 
354     Op = AcpiPsCreateScopeOp ();
355     if (!Op)
356     {
357         return (AE_NO_MEMORY);
358     }
359 
360     /* Create and initialize a new walk state */
361 
362     WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL);
363     if (!WalkState)
364     {
365         return (AE_NO_MEMORY);
366     }
367 
368     Status = AcpiDsInitAmlWalk (WalkState, Op, NULL,
369         ObjDesc->Method.AmlStart,
370         ObjDesc->Method.AmlLength, NULL, ACPI_IMODE_LOAD_PASS1);
371     if (ACPI_FAILURE (Status))
372     {
373         return (Status);
374     }
375 
376     Status = AcpiUtAllocateOwnerId (&ObjDesc->Method.OwnerId);
377     WalkState->OwnerId = ObjDesc->Method.OwnerId;
378 
379     /* Push start scope on scope stack and make it current */
380 
381     Status = AcpiDsScopeStackPush (Method,
382         Method->Type, WalkState);
383     if (ACPI_FAILURE (Status))
384     {
385         return (Status);
386     }
387 
388     /* Parse the entire method AML including deferred operators */
389 
390     WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;
391     WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE;
392 
393     Status = AcpiPsParseAml (WalkState);
394     (void) AcpiDmParseDeferredOps (Op);
395 
396     /* Now we can disassemble the method */
397 
398     AcpiGbl_DbOpt_verbose = FALSE;
399     AcpiDmDisassemble (NULL, Op, 0);
400     AcpiGbl_DbOpt_verbose = TRUE;
401 
402     AcpiPsDeleteParseTree (Op);
403 
404     /* Method cleanup */
405 
406     AcpiNsDeleteNamespaceSubtree (Method);
407     AcpiNsDeleteNamespaceByOwner (ObjDesc->Method.OwnerId);
408     AcpiUtReleaseOwnerId (&ObjDesc->Method.OwnerId);
409     return (AE_OK);
410 }
411 
412 #endif /* ACPI_DEBUGGER */
413