1 /*******************************************************************************
2  *
3  * Module Name: dbobject - ACPI object decode and display
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 "acnamesp.h"
47 #include "acdebug.h"
48 #ifdef ACPI_DISASSEMBLER
49 #include "acdisasm.h"
50 #endif
51 
52 
53 #ifdef ACPI_DEBUGGER
54 
55 #define _COMPONENT          ACPI_CA_DEBUGGER
56         ACPI_MODULE_NAME    ("dbobject")
57 
58 /* Local prototypes */
59 
60 static void
61 AcpiDbDecodeNode (
62     ACPI_NAMESPACE_NODE     *Node);
63 
64 
65 /*******************************************************************************
66  *
67  * FUNCTION:    AcpiDbDumpMethodInfo
68  *
69  * PARAMETERS:  Status          - Method execution status
70  *              WalkState       - Current state of the parse tree walk
71  *
72  * RETURN:      None
73  *
74  * DESCRIPTION: Called when a method has been aborted because of an error.
75  *              Dumps the method execution stack, and the method locals/args,
76  *              and disassembles the AML opcode that failed.
77  *
78  ******************************************************************************/
79 
80 void
81 AcpiDbDumpMethodInfo (
82     ACPI_STATUS             Status,
83     ACPI_WALK_STATE         *WalkState)
84 {
85     ACPI_THREAD_STATE       *Thread;
86 
87 
88     /* Ignore control codes, they are not errors */
89 
90     if ((Status & AE_CODE_MASK) == AE_CODE_CONTROL)
91     {
92         return;
93     }
94 
95     /* We may be executing a deferred opcode */
96 
97     if (WalkState->DeferredNode)
98     {
99         AcpiOsPrintf ("Executing subtree for Buffer/Package/Region\n");
100         return;
101     }
102 
103     /*
104      * If there is no Thread, we are not actually executing a method.
105      * This can happen when the iASL compiler calls the interpreter
106      * to perform constant folding.
107      */
108     Thread = WalkState->Thread;
109     if (!Thread)
110     {
111         return;
112     }
113 
114     /* Display the method locals and arguments */
115 
116     AcpiOsPrintf ("\n");
117     AcpiDbDecodeLocals (WalkState);
118     AcpiOsPrintf ("\n");
119     AcpiDbDecodeArguments (WalkState);
120     AcpiOsPrintf ("\n");
121 }
122 
123 
124 /*******************************************************************************
125  *
126  * FUNCTION:    AcpiDbDecodeInternalObject
127  *
128  * PARAMETERS:  ObjDesc         - Object to be displayed
129  *
130  * RETURN:      None
131  *
132  * DESCRIPTION: Short display of an internal object. Numbers/Strings/Buffers.
133  *
134  ******************************************************************************/
135 
136 void
137 AcpiDbDecodeInternalObject (
138     ACPI_OPERAND_OBJECT     *ObjDesc)
139 {
140     UINT32                  i;
141 
142 
143     if (!ObjDesc)
144     {
145         AcpiOsPrintf (" Uninitialized");
146         return;
147     }
148 
149     if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND)
150     {
151         AcpiOsPrintf (" %p [%s]", ObjDesc, AcpiUtGetDescriptorName (ObjDesc));
152         return;
153     }
154 
155     AcpiOsPrintf (" %s", AcpiUtGetObjectTypeName (ObjDesc));
156 
157     switch (ObjDesc->Common.Type)
158     {
159     case ACPI_TYPE_INTEGER:
160 
161         AcpiOsPrintf (" %8.8X%8.8X",
162                 ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value));
163         break;
164 
165     case ACPI_TYPE_STRING:
166 
167         AcpiOsPrintf ("(%u) \"%.24s",
168                 ObjDesc->String.Length, ObjDesc->String.Pointer);
169 
170         if (ObjDesc->String.Length > 24)
171         {
172             AcpiOsPrintf ("...");
173         }
174         else
175         {
176             AcpiOsPrintf ("\"");
177         }
178         break;
179 
180     case ACPI_TYPE_BUFFER:
181 
182         AcpiOsPrintf ("(%u)", ObjDesc->Buffer.Length);
183         for (i = 0; (i < 8) && (i < ObjDesc->Buffer.Length); i++)
184         {
185             AcpiOsPrintf (" %2.2X", ObjDesc->Buffer.Pointer[i]);
186         }
187         break;
188 
189     default:
190 
191         AcpiOsPrintf (" %p", ObjDesc);
192         break;
193     }
194 }
195 
196 
197 /*******************************************************************************
198  *
199  * FUNCTION:    AcpiDbDecodeNode
200  *
201  * PARAMETERS:  Node        - Object to be displayed
202  *
203  * RETURN:      None
204  *
205  * DESCRIPTION: Short display of a namespace node
206  *
207  ******************************************************************************/
208 
209 static void
210 AcpiDbDecodeNode (
211     ACPI_NAMESPACE_NODE     *Node)
212 {
213 
214     AcpiOsPrintf ("<Node>            Name %4.4s",
215             AcpiUtGetNodeName (Node));
216 
217     if (Node->Flags & ANOBJ_METHOD_ARG)
218     {
219         AcpiOsPrintf (" [Method Arg]");
220     }
221     if (Node->Flags & ANOBJ_METHOD_LOCAL)
222     {
223         AcpiOsPrintf (" [Method Local]");
224     }
225 
226     switch (Node->Type)
227     {
228     /* These types have no attached object */
229 
230     case ACPI_TYPE_DEVICE:
231 
232         AcpiOsPrintf (" Device");
233         break;
234 
235     case ACPI_TYPE_THERMAL:
236 
237         AcpiOsPrintf (" Thermal Zone");
238         break;
239 
240     default:
241 
242         AcpiDbDecodeInternalObject (AcpiNsGetAttachedObject (Node));
243         break;
244     }
245 }
246 
247 
248 /*******************************************************************************
249  *
250  * FUNCTION:    AcpiDbDisplayInternalObject
251  *
252  * PARAMETERS:  ObjDesc         - Object to be displayed
253  *              WalkState       - Current walk state
254  *
255  * RETURN:      None
256  *
257  * DESCRIPTION: Short display of an internal object
258  *
259  ******************************************************************************/
260 
261 void
262 AcpiDbDisplayInternalObject (
263     ACPI_OPERAND_OBJECT     *ObjDesc,
264     ACPI_WALK_STATE         *WalkState)
265 {
266     UINT8                   Type;
267 
268 
269     AcpiOsPrintf ("%p ", ObjDesc);
270 
271     if (!ObjDesc)
272     {
273         AcpiOsPrintf ("<Null Object>\n");
274         return;
275     }
276 
277     /* Decode the object type */
278 
279     switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))
280     {
281     case ACPI_DESC_TYPE_PARSER:
282 
283         AcpiOsPrintf ("<Parser>  ");
284         break;
285 
286     case ACPI_DESC_TYPE_NAMED:
287 
288         AcpiDbDecodeNode ((ACPI_NAMESPACE_NODE *) ObjDesc);
289         break;
290 
291     case ACPI_DESC_TYPE_OPERAND:
292 
293         Type = ObjDesc->Common.Type;
294         if (Type > ACPI_TYPE_LOCAL_MAX)
295         {
296             AcpiOsPrintf (" Type %X [Invalid Type]", (UINT32) Type);
297             return;
298         }
299 
300         /* Decode the ACPI object type */
301 
302         switch (ObjDesc->Common.Type)
303         {
304         case ACPI_TYPE_LOCAL_REFERENCE:
305 
306             AcpiOsPrintf ("[%s] ", AcpiUtGetReferenceName (ObjDesc));
307 
308             /* Decode the refererence */
309 
310             switch (ObjDesc->Reference.Class)
311             {
312             case ACPI_REFCLASS_LOCAL:
313 
314                 AcpiOsPrintf ("%X ", ObjDesc->Reference.Value);
315                 if (WalkState)
316                 {
317                     ObjDesc = WalkState->LocalVariables
318                                 [ObjDesc->Reference.Value].Object;
319                     AcpiOsPrintf ("%p", ObjDesc);
320                     AcpiDbDecodeInternalObject (ObjDesc);
321                 }
322                 break;
323 
324             case ACPI_REFCLASS_ARG:
325 
326                 AcpiOsPrintf ("%X ", ObjDesc->Reference.Value);
327                 if (WalkState)
328                 {
329                     ObjDesc = WalkState->Arguments
330                                 [ObjDesc->Reference.Value].Object;
331                     AcpiOsPrintf ("%p", ObjDesc);
332                     AcpiDbDecodeInternalObject (ObjDesc);
333                 }
334                 break;
335 
336             case ACPI_REFCLASS_INDEX:
337 
338                 switch (ObjDesc->Reference.TargetType)
339                 {
340                 case ACPI_TYPE_BUFFER_FIELD:
341 
342                     AcpiOsPrintf ("%p", ObjDesc->Reference.Object);
343                     AcpiDbDecodeInternalObject (ObjDesc->Reference.Object);
344                     break;
345 
346                 case ACPI_TYPE_PACKAGE:
347 
348                     AcpiOsPrintf ("%p", ObjDesc->Reference.Where);
349                     if (!ObjDesc->Reference.Where)
350                     {
351                         AcpiOsPrintf (" Uninitialized WHERE pointer");
352                     }
353                     else
354                     {
355                         AcpiDbDecodeInternalObject (
356                             *(ObjDesc->Reference.Where));
357                     }
358                     break;
359 
360                 default:
361 
362                     AcpiOsPrintf ("Unknown index target type");
363                     break;
364                 }
365                 break;
366 
367             case ACPI_REFCLASS_REFOF:
368 
369                 if (!ObjDesc->Reference.Object)
370                 {
371                     AcpiOsPrintf ("Uninitialized reference subobject pointer");
372                     break;
373                 }
374 
375                 /* Reference can be to a Node or an Operand object */
376 
377                 switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc->Reference.Object))
378                 {
379                 case ACPI_DESC_TYPE_NAMED:
380                     AcpiDbDecodeNode (ObjDesc->Reference.Object);
381                     break;
382 
383                 case ACPI_DESC_TYPE_OPERAND:
384                     AcpiDbDecodeInternalObject (ObjDesc->Reference.Object);
385                     break;
386 
387                 default:
388                     break;
389                 }
390                 break;
391 
392             case ACPI_REFCLASS_NAME:
393 
394                 AcpiDbDecodeNode (ObjDesc->Reference.Node);
395                 break;
396 
397             case ACPI_REFCLASS_DEBUG:
398             case ACPI_REFCLASS_TABLE:
399 
400                 AcpiOsPrintf ("\n");
401                 break;
402 
403             default:    /* Unknown reference class */
404 
405                 AcpiOsPrintf ("%2.2X\n", ObjDesc->Reference.Class);
406                 break;
407             }
408             break;
409 
410         default:
411 
412             AcpiOsPrintf ("<Obj>            ");
413             AcpiDbDecodeInternalObject (ObjDesc);
414             break;
415         }
416         break;
417 
418     default:
419 
420         AcpiOsPrintf ("<Not a valid ACPI Object Descriptor> [%s]",
421             AcpiUtGetDescriptorName (ObjDesc));
422         break;
423     }
424 
425     AcpiOsPrintf ("\n");
426 }
427 
428 
429 /*******************************************************************************
430  *
431  * FUNCTION:    AcpiDbDecodeLocals
432  *
433  * PARAMETERS:  WalkState       - State for current method
434  *
435  * RETURN:      None
436  *
437  * DESCRIPTION: Display all locals for the currently running control method
438  *
439  ******************************************************************************/
440 
441 void
442 AcpiDbDecodeLocals (
443     ACPI_WALK_STATE         *WalkState)
444 {
445     UINT32                  i;
446     ACPI_OPERAND_OBJECT     *ObjDesc;
447     ACPI_NAMESPACE_NODE     *Node;
448 
449 
450     ObjDesc = WalkState->MethodDesc;
451     Node    = WalkState->MethodNode;
452     if (!Node)
453     {
454         AcpiOsPrintf (
455             "No method node (Executing subtree for buffer or opregion)\n");
456         return;
457     }
458 
459     if (Node->Type != ACPI_TYPE_METHOD)
460     {
461         AcpiOsPrintf ("Executing subtree for Buffer/Package/Region\n");
462         return;
463     }
464 
465     AcpiOsPrintf ("Local Variables for method [%4.4s]:\n",
466             AcpiUtGetNodeName (Node));
467 
468     for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++)
469     {
470         ObjDesc = WalkState->LocalVariables[i].Object;
471         AcpiOsPrintf ("    Local%X: ", i);
472         AcpiDbDisplayInternalObject (ObjDesc, WalkState);
473     }
474 }
475 
476 
477 /*******************************************************************************
478  *
479  * FUNCTION:    AcpiDbDecodeArguments
480  *
481  * PARAMETERS:  WalkState       - State for current method
482  *
483  * RETURN:      None
484  *
485  * DESCRIPTION: Display all arguments for the currently running control method
486  *
487  ******************************************************************************/
488 
489 void
490 AcpiDbDecodeArguments (
491     ACPI_WALK_STATE         *WalkState)
492 {
493     UINT32                  i;
494     ACPI_OPERAND_OBJECT     *ObjDesc;
495     ACPI_NAMESPACE_NODE     *Node;
496 
497 
498     ObjDesc = WalkState->MethodDesc;
499     Node    = WalkState->MethodNode;
500     if (!Node)
501     {
502         AcpiOsPrintf (
503             "No method node (Executing subtree for buffer or opregion)\n");
504         return;
505     }
506 
507     if (Node->Type != ACPI_TYPE_METHOD)
508     {
509         AcpiOsPrintf ("Executing subtree for Buffer/Package/Region\n");
510         return;
511     }
512 
513     AcpiOsPrintf (
514         "Arguments for Method [%4.4s]:  (%X arguments defined, max concurrency = %X)\n",
515         AcpiUtGetNodeName (Node), ObjDesc->Method.ParamCount, ObjDesc->Method.SyncLevel);
516 
517     for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++)
518     {
519         ObjDesc = WalkState->Arguments[i].Object;
520         AcpiOsPrintf ("    Arg%u:   ", i);
521         AcpiDbDisplayInternalObject (ObjDesc, WalkState);
522     }
523 }
524 
525 #endif
526