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 */