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