dbmethod.c revision 1.5 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 #ifdef ACPI_DISASSEMBLER
50 #include "acdisasm.h"
51 #endif
52 #include "acparser.h"
53 #include "acpredef.h"
54
55
56 #ifdef ACPI_DEBUGGER
57
58 #define _COMPONENT ACPI_CA_DEBUGGER
59 ACPI_MODULE_NAME ("dbmethod")
60
61
62 /*******************************************************************************
63 *
64 * FUNCTION: AcpiDbSetMethodBreakpoint
65 *
66 * PARAMETERS: Location - AML offset of breakpoint
67 * WalkState - Current walk info
68 * Op - Current Op (from parse walk)
69 *
70 * RETURN: None
71 *
72 * DESCRIPTION: Set a breakpoint in a control method at the specified
73 * AML offset
74 *
75 ******************************************************************************/
76
77 void
78 AcpiDbSetMethodBreakpoint (
79 char *Location,
80 ACPI_WALK_STATE *WalkState,
81 ACPI_PARSE_OBJECT *Op)
82 {
83 UINT32 Address;
84 UINT32 AmlOffset;
85
86
87 if (!Op)
88 {
89 AcpiOsPrintf ("There is no method currently executing\n");
90 return;
91 }
92
93 /* Get and verify the breakpoint address */
94
95 Address = strtoul (Location, NULL, 16);
96 AmlOffset = (UINT32) ACPI_PTR_DIFF (Op->Common.Aml,
97 WalkState->ParserState.AmlStart);
98 if (Address <= AmlOffset)
99 {
100 AcpiOsPrintf ("Breakpoint %X is beyond current address %X\n",
101 Address, AmlOffset);
102 }
103
104 /* Save breakpoint in current walk */
105
106 WalkState->UserBreakpoint = Address;
107 AcpiOsPrintf ("Breakpoint set at AML offset %X\n", Address);
108 }
109
110
111 /*******************************************************************************
112 *
113 * FUNCTION: AcpiDbSetMethodCallBreakpoint
114 *
115 * PARAMETERS: Op - Current Op (from parse walk)
116 *
117 * RETURN: None
118 *
119 * DESCRIPTION: Set a breakpoint in a control method at the specified
120 * AML offset
121 *
122 ******************************************************************************/
123
124 void
125 AcpiDbSetMethodCallBreakpoint (
126 ACPI_PARSE_OBJECT *Op)
127 {
128
129
130 if (!Op)
131 {
132 AcpiOsPrintf ("There is no method currently executing\n");
133 return;
134 }
135
136 AcpiGbl_StepToNextCall = TRUE;
137 }
138
139
140 /*******************************************************************************
141 *
142 * FUNCTION: AcpiDbSetMethodData
143 *
144 * PARAMETERS: TypeArg - L for local, A for argument
145 * IndexArg - which one
146 * ValueArg - Value to set.
147 *
148 * RETURN: None
149 *
150 * DESCRIPTION: Set a local or argument for the running control method.
151 * NOTE: only object supported is Number.
152 *
153 ******************************************************************************/
154
155 void
156 AcpiDbSetMethodData (
157 char *TypeArg,
158 char *IndexArg,
159 char *ValueArg)
160 {
161 char Type;
162 UINT32 Index;
163 UINT32 Value;
164 ACPI_WALK_STATE *WalkState;
165 ACPI_OPERAND_OBJECT *ObjDesc;
166 ACPI_STATUS Status;
167 ACPI_NAMESPACE_NODE *Node;
168
169
170 /* Validate TypeArg */
171
172 AcpiUtStrupr (TypeArg);
173 Type = TypeArg[0];
174 if ((Type != 'L') &&
175 (Type != 'A') &&
176 (Type != 'N'))
177 {
178 AcpiOsPrintf ("Invalid SET operand: %s\n", TypeArg);
179 return;
180 }
181
182 Value = strtoul (ValueArg, NULL, 16);
183
184 if (Type == 'N')
185 {
186 Node = AcpiDbConvertToNode (IndexArg);
187 if (!Node)
188 {
189 return;
190 }
191
192 if (Node->Type != ACPI_TYPE_INTEGER)
193 {
194 AcpiOsPrintf ("Can only set Integer nodes\n");
195 return;
196 }
197 ObjDesc = Node->Object;
198 ObjDesc->Integer.Value = Value;
199 return;
200 }
201
202 /* Get the index and value */
203
204 Index = strtoul (IndexArg, NULL, 16);
205
206 WalkState = AcpiDsGetCurrentWalkState (AcpiGbl_CurrentWalkList);
207 if (!WalkState)
208 {
209 AcpiOsPrintf ("There is no method currently executing\n");
210 return;
211 }
212
213 /* Create and initialize the new object */
214
215 ObjDesc = AcpiUtCreateIntegerObject ((UINT64) Value);
216 if (!ObjDesc)
217 {
218 AcpiOsPrintf ("Could not create an internal object\n");
219 return;
220 }
221
222 /* Store the new object into the target */
223
224 switch (Type)
225 {
226 case 'A':
227
228 /* Set a method argument */
229
230 if (Index > ACPI_METHOD_MAX_ARG)
231 {
232 AcpiOsPrintf ("Arg%u - Invalid argument name\n", Index);
233 goto Cleanup;
234 }
235
236 Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_ARG, Index, ObjDesc,
237 WalkState);
238 if (ACPI_FAILURE (Status))
239 {
240 goto Cleanup;
241 }
242
243 ObjDesc = WalkState->Arguments[Index].Object;
244
245 AcpiOsPrintf ("Arg%u: ", Index);
246 AcpiDbDisplayInternalObject (ObjDesc, WalkState);
247 break;
248
249 case 'L':
250
251 /* Set a method local */
252
253 if (Index > ACPI_METHOD_MAX_LOCAL)
254 {
255 AcpiOsPrintf ("Local%u - Invalid local variable name\n", Index);
256 goto Cleanup;
257 }
258
259 Status = AcpiDsStoreObjectToLocal (ACPI_REFCLASS_LOCAL, Index, ObjDesc,
260 WalkState);
261 if (ACPI_FAILURE (Status))
262 {
263 goto Cleanup;
264 }
265
266 ObjDesc = WalkState->LocalVariables[Index].Object;
267
268 AcpiOsPrintf ("Local%u: ", Index);
269 AcpiDbDisplayInternalObject (ObjDesc, WalkState);
270 break;
271
272 default:
273
274 break;
275 }
276
277 Cleanup:
278 AcpiUtRemoveReference (ObjDesc);
279 }
280
281
282 /*******************************************************************************
283 *
284 * FUNCTION: AcpiDbDisassembleAml
285 *
286 * PARAMETERS: Statements - Number of statements to disassemble
287 * Op - Current Op (from parse walk)
288 *
289 * RETURN: None
290 *
291 * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number
292 * of statements specified.
293 *
294 ******************************************************************************/
295
296 void
297 AcpiDbDisassembleAml (
298 char *Statements,
299 ACPI_PARSE_OBJECT *Op)
300 {
301 UINT32 NumStatements = 8;
302
303
304 if (!Op)
305 {
306 AcpiOsPrintf ("There is no method currently executing\n");
307 return;
308 }
309
310 if (Statements)
311 {
312 NumStatements = strtoul (Statements, NULL, 0);
313 }
314
315 #ifdef ACPI_DISASSEMBLER
316 AcpiDmDisassemble (NULL, Op, NumStatements);
317 #endif
318 }
319
320
321 /*******************************************************************************
322 *
323 * FUNCTION: AcpiDbDisassembleMethod
324 *
325 * PARAMETERS: Name - Name of control method
326 *
327 * RETURN: None
328 *
329 * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number
330 * of statements specified.
331 *
332 ******************************************************************************/
333
334 ACPI_STATUS
335 AcpiDbDisassembleMethod (
336 char *Name)
337 {
338 ACPI_STATUS Status;
339 ACPI_PARSE_OBJECT *Op;
340 ACPI_WALK_STATE *WalkState;
341 ACPI_OPERAND_OBJECT *ObjDesc;
342 ACPI_NAMESPACE_NODE *Method;
343
344
345 Method = AcpiDbConvertToNode (Name);
346 if (!Method)
347 {
348 return (AE_BAD_PARAMETER);
349 }
350
351 if (Method->Type != ACPI_TYPE_METHOD)
352 {
353 ACPI_ERROR ((AE_INFO, "%s (%s): Object must be a control method",
354 Name, AcpiUtGetTypeName (Method->Type)));
355 return (AE_BAD_PARAMETER);
356 }
357
358 ObjDesc = Method->Object;
359
360 Op = AcpiPsCreateScopeOp (ObjDesc->Method.AmlStart);
361 if (!Op)
362 {
363 return (AE_NO_MEMORY);
364 }
365
366 /* Create and initialize a new walk state */
367
368 WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL);
369 if (!WalkState)
370 {
371 return (AE_NO_MEMORY);
372 }
373
374 Status = AcpiDsInitAmlWalk (WalkState, Op, NULL,
375 ObjDesc->Method.AmlStart,
376 ObjDesc->Method.AmlLength, NULL, ACPI_IMODE_LOAD_PASS1);
377 if (ACPI_FAILURE (Status))
378 {
379 return (Status);
380 }
381
382 Status = AcpiUtAllocateOwnerId (&ObjDesc->Method.OwnerId);
383 WalkState->OwnerId = ObjDesc->Method.OwnerId;
384
385 /* Push start scope on scope stack and make it current */
386
387 Status = AcpiDsScopeStackPush (Method,
388 Method->Type, WalkState);
389 if (ACPI_FAILURE (Status))
390 {
391 return (Status);
392 }
393
394 /* Parse the entire method AML including deferred operators */
395
396 WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;
397 WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE;
398
399 Status = AcpiPsParseAml (WalkState);
400
401 #ifdef ACPI_DISASSEMBER
402 (void) AcpiDmParseDeferredOps (Op);
403
404 /* Now we can disassemble the method */
405
406 AcpiGbl_DbOpt_Verbose = FALSE;
407 AcpiDmDisassemble (NULL, Op, 0);
408 AcpiGbl_DbOpt_Verbose = TRUE;
409 #endif
410
411 AcpiPsDeleteParseTree (Op);
412
413 /* Method cleanup */
414
415 AcpiNsDeleteNamespaceSubtree (Method);
416 AcpiNsDeleteNamespaceByOwner (ObjDesc->Method.OwnerId);
417 AcpiUtReleaseOwnerId (&ObjDesc->Method.OwnerId);
418 return (AE_OK);
419 }
420
421 #endif /* ACPI_DEBUGGER */
422