1 /******************************************************************************
2  *
3  * Module Name: aslxrefout.c - support for optional cross-reference file
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2016, 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 "aslcompiler.h"
45 #include "aslcompiler.y.h"
46 #include "acnamesp.h"
47 #include "acparser.h"
48 #include "amlcode.h"
49 
50 #define _COMPONENT          ACPI_COMPILER
51         ACPI_MODULE_NAME    ("aslxrefout")
52 
53 
54 /* Local prototypes */
55 
56 static ACPI_STATUS
57 OtXrefWalkPart2 (
58     ACPI_PARSE_OBJECT       *Op,
59     UINT32                  Level,
60     void                    *Context);
61 
62 static ACPI_STATUS
63 OtXrefWalkPart3 (
64     ACPI_PARSE_OBJECT       *Op,
65     UINT32                  Level,
66     void                    *Context);
67 
68 static ACPI_STATUS
69 OtXrefAnalysisWalkPart1 (
70     ACPI_PARSE_OBJECT       *Op,
71     UINT32                  Level,
72     void                    *Context);
73 
74 
75 static ACPI_STATUS
76 OtXrefAnalysisWalkPart2 (
77     ACPI_PARSE_OBJECT       *Op,
78     UINT32                  Level,
79     void                    *Context);
80 
81 static ACPI_STATUS
82 OtXrefAnalysisWalkPart3 (
83     ACPI_PARSE_OBJECT       *Op,
84     UINT32                  Level,
85     void                    *Context);
86 
87 
88 /*******************************************************************************
89  *
90  * FUNCTION:    OtPrintHeaders
91  *
92  * PARAMETERS:  Message             - Main header message
93  *
94  * RETURN:      None
95  *
96  * DESCRIPTION: Emits the main header message along with field descriptions
97  *
98  ******************************************************************************/
99 
100 void
101 OtPrintHeaders (
102     char                    *Message)
103 {
104     UINT32                  Length;
105 
106 
107     Length = strlen (Message);
108 
109     FlPrintFile (ASL_FILE_XREF_OUTPUT, "\n\n%s\n", Message);
110     while (Length)
111     {
112         FlPrintFile (ASL_FILE_XREF_OUTPUT, "-");
113         Length--;
114     }
115 
116     FlPrintFile (ASL_FILE_XREF_OUTPUT, "\n\nLineno   %-40s Description\n",
117         "Full Pathname");
118 }
119 
120 
121 /*******************************************************************************
122  *
123  * FUNCTION:    OtCreateXrefFile
124  *
125  * PARAMETERS:  None
126  *
127  * RETURN:      None
128  *
129  * DESCRIPTION  Main entry point for parts 2 and 3 of the cross-reference
130  *              file.
131  *
132  ******************************************************************************/
133 
134 void
135 OtCreateXrefFile (
136     void)
137 {
138     ASL_XREF_INFO           XrefInfo;
139 
140 
141     /* Build cross-reference output file if requested */
142 
143     if (!Gbl_CrossReferenceOutput)
144     {
145         return;
146     }
147 
148     memset (&XrefInfo, 0, sizeof (ASL_XREF_INFO));
149 
150     /* Cross-reference output file, part 2 (Method invocations) */
151 
152     OtPrintHeaders ("Part 2: Method Reference Map "
153         "(Invocations of each user-defined control method)");
154 
155     TrWalkParseTree (Gbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD,
156         OtXrefWalkPart2, NULL, &XrefInfo);
157 
158     /* Cross-reference output file, part 3 (All other object refs) */
159 
160     OtPrintHeaders ("Part 3: Full Object Reference Map "
161         "(Methods that reference each object in namespace");
162 
163     TrWalkParseTree (Gbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD,
164         OtXrefWalkPart3, NULL, &XrefInfo);
165 
166     /* Cross-reference summary */
167 
168     FlPrintFile (ASL_FILE_XREF_OUTPUT, "\n\nObject Summary\n");
169 
170     FlPrintFile (ASL_FILE_XREF_OUTPUT,
171         "\nTotal methods:                   %u\n",
172         XrefInfo.TotalPredefinedMethods + XrefInfo.TotalUserMethods);
173     FlPrintFile (ASL_FILE_XREF_OUTPUT,
174         "Total predefined methods:        %u\n",
175         XrefInfo.TotalPredefinedMethods);
176 
177     FlPrintFile (ASL_FILE_XREF_OUTPUT,
178         "\nTotal user methods:              %u\n",
179         XrefInfo.TotalUserMethods);
180     FlPrintFile (ASL_FILE_XREF_OUTPUT,
181         "Total unreferenced user methods  %u\n",
182         XrefInfo.TotalUnreferenceUserMethods);
183 
184     FlPrintFile (ASL_FILE_XREF_OUTPUT,
185         "\nTotal defined objects:           %u\n",
186         XrefInfo.TotalObjects);
187     FlPrintFile (ASL_FILE_XREF_OUTPUT,
188         "Total unreferenced objects:      %u\n",
189         XrefInfo.TotalUnreferencedObjects);
190 }
191 
192 
193 /*
194  * Part 1 of the cross reference file. This part emits the namespace objects
195  * that are referenced by each control method in the namespace.
196  *
197  * Part 2 and 3 are below part 1.
198  */
199 
200 /*******************************************************************************
201  *
202  * FUNCTION:    OtXrefWalkPart1
203  *
204  * PARAMETERS:  Op                      - Current parse Op
205  *              Level                   - Current tree nesting level
206  *              MethodInfo              - Info block for the current method
207  *
208  *
209  * RETURN:      None
210  *
211  * DESCRIPTION: Entry point for the creation of the method call reference map.
212  *              For each control method in the namespace, all other methods
213  *              that invoke the method are listed. Predefined names/methods
214  *              that start with an underscore are ignored, because these are
215  *              essentially external/public interfaces.
216 
217  * DESCRIPTION: Entry point for the creation of the object reference map.
218  *              For each control method in the namespace, all objects that
219  *              are referenced by the method are listed.
220  *
221  *              Called during a normal namespace walk, once per namespace
222  *              object. (MtMethodAnalysisWalkBegin)
223  *
224  ******************************************************************************/
225 
226 void
227 OtXrefWalkPart1 (
228     ACPI_PARSE_OBJECT       *Op,
229     UINT32                  Level,
230     ASL_METHOD_INFO         *MethodInfo)
231 {
232     ACPI_NAMESPACE_NODE     *Node;
233     ACPI_PARSE_OBJECT       *NextOp;
234     ACPI_PARSE_OBJECT       *FieldOp;
235     char                    *ParentPath;
236     UINT32                  Length;
237     ACPI_STATUS             Status;
238 
239 
240     switch (Op->Asl.ParseOpcode)
241     {
242     case PARSEOP_NAMESEG:
243     case PARSEOP_NAMESTRING:
244     case PARSEOP_METHODCALL:
245 
246         if (!MethodInfo ||
247             (MethodInfo->Op->Asl.Child == Op) ||
248             !Op->Asl.Node)
249         {
250             break;
251         }
252 
253         MethodInfo->CurrentOp = Op;
254         Node = Op->Asl.Node;
255         ParentPath = AcpiNsGetNormalizedPathname (Node, TRUE);
256 
257         /* Find all objects referenced by this method */
258 
259         Status = TrWalkParseTree (MethodInfo->Op, ASL_WALK_VISIT_DOWNWARD,
260             OtXrefAnalysisWalkPart1, NULL, MethodInfo);
261 
262         if (Status == AE_CTRL_TERMINATE)
263         {
264             FlPrintFile (ASL_FILE_XREF_OUTPUT, "            %-40s %s",
265                 ParentPath, AcpiUtGetTypeName (Node->Type));
266 
267             switch (Node->Type)
268             {
269                 /* Handle externals */
270 
271             case ACPI_TYPE_ANY:
272             case ACPI_TYPE_FIELD_UNIT:
273 
274                 FlPrintFile (ASL_FILE_XREF_OUTPUT, " <External Object>");
275                 break;
276 
277             case ACPI_TYPE_INTEGER:
278 
279                 FlPrintFile (ASL_FILE_XREF_OUTPUT, " %8.8X%8.8X",
280                     ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer));
281                 break;
282 
283             case ACPI_TYPE_METHOD:
284 
285                 FlPrintFile (ASL_FILE_XREF_OUTPUT, " Invocation (%u args)",
286                     Node->ArgCount);
287                 break;
288 
289             case ACPI_TYPE_BUFFER_FIELD:
290 
291                 NextOp = Node->Op;              /* Create Buffer Field Op */
292                 switch (NextOp->Asl.ParseOpcode)
293                 {
294                 case PARSEOP_CREATEBITFIELD:
295                     Length = 1;
296                     break;
297 
298                 case PARSEOP_CREATEBYTEFIELD:
299                     Length = 8;
300                     break;
301 
302                 case PARSEOP_CREATEWORDFIELD:
303                     Length = 16;
304                     break;
305 
306                 case PARSEOP_CREATEDWORDFIELD:
307                     Length = 32;
308                     break;
309 
310                 case PARSEOP_CREATEQWORDFIELD:
311                     Length = 64;
312                     break;
313 
314                 default:
315                     Length = 0;
316                     break;
317                 }
318 
319                 NextOp = NextOp->Asl.Child;     /* Buffer name */
320 
321                 if (!NextOp->Asl.ExternalName)
322                 {
323                     FlPrintFile (ASL_FILE_XREF_OUTPUT, " in Arg/Local");
324                 }
325                 else
326                 {
327                     ACPI_FREE (ParentPath);
328                     ParentPath = AcpiNsGetNormalizedPathname (
329                         NextOp->Asl.Node, TRUE);
330 
331                     FlPrintFile (ASL_FILE_XREF_OUTPUT, " (%.2u bit) in Buffer %s",
332                         Length, ParentPath);
333                 }
334                 break;
335 
336             case ACPI_TYPE_LOCAL_REGION_FIELD:
337 
338                 NextOp = Node->Op;
339                 FieldOp = NextOp->Asl.Parent;
340                 NextOp = FieldOp->Asl.Child;
341 
342                 ACPI_FREE (ParentPath);
343                 ParentPath = AcpiNsGetNormalizedPathname (
344                     NextOp->Asl.Node, TRUE);
345 
346                 FlPrintFile (ASL_FILE_XREF_OUTPUT, " (%.2u bit) in Region %s",
347                     (UINT32) Node->Op->Asl.Child->Asl.Value.Integer,
348                     ParentPath);
349 
350                 if (FieldOp->Asl.ParseOpcode == PARSEOP_FIELD)
351                 {
352                     Node = NextOp->Asl.Node;        /* Region node */
353                     NextOp = Node->Op;              /* PARSEOP_REGION */
354                     NextOp = NextOp->Asl.Child;     /* Region name */
355                     NextOp = NextOp->Asl.Next;
356 
357                     /* Get region space/addr/len? */
358 
359                     FlPrintFile (ASL_FILE_XREF_OUTPUT, " (%s)",
360                         AcpiUtGetRegionName ((UINT8)
361                         NextOp->Asl.Value.Integer));
362                 }
363                 break;
364 
365             default:
366                 break;
367             }
368 
369             FlPrintFile (ASL_FILE_XREF_OUTPUT, "\n");
370             ACPI_FREE (ParentPath);
371         }
372         break;
373 
374     case PARSEOP_METHOD:
375 
376         ParentPath = AcpiNsGetNormalizedPathname (Op->Asl.Node, TRUE);
377 
378         FlPrintFile (ASL_FILE_XREF_OUTPUT,
379             "\n[%5u]  %-40s %s Declaration (%u args)\n",
380             Op->Asl.LogicalLineNumber, ParentPath,
381             AcpiUtGetTypeName (Op->Asl.Node->Type), Op->Asl.Node->ArgCount);
382 
383         ACPI_FREE (ParentPath);
384         break;
385 
386     default:
387         break;
388     }
389 }
390 
391 
392 /*******************************************************************************
393  *
394  * FUNCTION:    OtXrefAnalysisWalkPart1
395  *
396  * PARAMETERS:  ASL_WALK_CALLBACK
397  *
398  * RETURN:      Status
399  *
400  * DESCRIPTION: Secondary walk for cross-reference part 1.
401  *
402  ******************************************************************************/
403 
404 static ACPI_STATUS
405 OtXrefAnalysisWalkPart1 (
406     ACPI_PARSE_OBJECT       *Op,
407     UINT32                  Level,
408     void                    *Context)
409 {
410     ASL_METHOD_INFO         *MethodInfo = (ASL_METHOD_INFO *) Context;
411     ACPI_PARSE_OBJECT       *Next;
412 
413 
414     /* Only interested in name string Ops -- ignore all others */
415 
416     if ((Op->Asl.ParseOpcode != PARSEOP_NAMESEG) &&
417         (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) &&
418         (Op->Asl.ParseOpcode != PARSEOP_METHODCALL))
419     {
420         return (AE_OK);
421     }
422 
423     /* No node means a locally declared object -- ignore */
424 
425     if (!Op->Asl.Node)
426     {
427         return (AE_OK);
428     }
429 
430     /* When we encounter the source Op, we are done */
431 
432     Next = MethodInfo->CurrentOp;
433     if (Next == Op)
434     {
435         return (AE_CTRL_TERMINATE);
436     }
437 
438     /* If we have a name match, this Op is a duplicate */
439 
440     if ((Next->Asl.ParseOpcode == PARSEOP_NAMESEG)      ||
441         (Next->Asl.ParseOpcode == PARSEOP_NAMESTRING)   ||
442         (Next->Asl.ParseOpcode == PARSEOP_METHODCALL))
443     {
444         if (!strcmp (Op->Asl.ExternalName, Next->Asl.ExternalName))
445         {
446             return (AE_ALREADY_EXISTS);
447         }
448     }
449 
450     return (AE_OK);
451 }
452 
453 
454 /*
455  * Part 2 of the cross reference file. This part emits the names of each
456  * non-predefined method in the namespace (user methods), along with the
457  * names of each control method that references that method.
458  */
459 
460 /*******************************************************************************
461  *
462  * FUNCTION:    OtXrefWalkPart2
463  *
464  * PARAMETERS:  ASL_WALK_CALLBACK
465  *
466  * RETURN:      Status
467  *
468  * DESCRIPTION: For each control method in the namespace, we will re-walk the
469  *              namespace to find each and every invocation of that control
470  *              method. Brute force, but does not matter, even for large
471  *              namespaces. Ignore predefined names (start with underscore).
472  *
473  ******************************************************************************/
474 
475 static ACPI_STATUS
476 OtXrefWalkPart2 (
477     ACPI_PARSE_OBJECT       *Op,
478     UINT32                  Level,
479     void                    *Context)
480 {
481     ASL_XREF_INFO           *XrefInfo = (ASL_XREF_INFO *) Context;
482     ACPI_NAMESPACE_NODE     *Node;
483     char                    *ParentPath;
484 
485 
486     /* Looking for Method Declaration Ops only */
487 
488     if (!Op->Asl.Node ||
489         (Op->Asl.ParseOpcode != PARSEOP_METHOD))
490     {
491         return (AE_OK);
492     }
493 
494     /* Ignore predefined names */
495 
496     if (Op->Asl.Node->Name.Ascii[0] == '_')
497     {
498         XrefInfo->TotalPredefinedMethods++;
499         return (AE_OK);
500     }
501 
502     Node = Op->Asl.Node;
503     ParentPath = AcpiNsGetNormalizedPathname (Node, TRUE);
504 
505     FlPrintFile (ASL_FILE_XREF_OUTPUT,
506         "\n[%5u]  %-40s %s Declaration (%u args)\n",
507         Op->Asl.LogicalLineNumber, ParentPath,
508         AcpiUtGetTypeName (Node->Type), Node->ArgCount);
509 
510     XrefInfo->TotalUserMethods++;
511     XrefInfo->ThisMethodInvocations = 0;
512     XrefInfo->MethodOp = Op;
513 
514     (void) TrWalkParseTree (Gbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD,
515         OtXrefAnalysisWalkPart2, NULL, XrefInfo);
516 
517     if (!XrefInfo->ThisMethodInvocations)
518     {
519         FlPrintFile (ASL_FILE_XREF_OUTPUT,
520             "            Zero invocations of this method in this module\n");
521         XrefInfo->TotalUnreferenceUserMethods++;
522     }
523     else
524     {
525         FlPrintFile (ASL_FILE_XREF_OUTPUT,
526             "            %u invocations of method %s in this module\n",
527             XrefInfo->ThisMethodInvocations, ParentPath);
528     }
529 
530     ACPI_FREE (ParentPath);
531     return (AE_OK);
532 }
533 
534 
535 /*******************************************************************************
536  *
537  * FUNCTION:    OtXrefAnalysisWalkPart2
538  *
539  * PARAMETERS:  ASL_WALK_CALLBACK
540  *
541  * RETURN:      Status
542  *
543  * DESCRIPTION: For every Op that is a method invocation, emit a reference
544  *              line if the Op is invoking the target method.
545  *
546  ******************************************************************************/
547 
548 static ACPI_STATUS
549 OtXrefAnalysisWalkPart2 (
550     ACPI_PARSE_OBJECT       *Op,
551     UINT32                  Level,
552     void                    *Context)
553 {
554     ASL_XREF_INFO           *XrefInfo = (ASL_XREF_INFO *) Context;
555     ACPI_PARSE_OBJECT       *CallerOp;
556     char                    *CallerFullPathname;
557 
558 
559     /* Looking for MethodCall Ops only */
560 
561     if (!Op->Asl.Node ||
562         (Op->Asl.ParseOpcode != PARSEOP_METHODCALL))
563     {
564         return (AE_OK);
565     }
566 
567     /* If not a match to the target method, we are done */
568 
569     if (Op->Asl.Node != XrefInfo->MethodOp->Asl.Node)
570     {
571         return (AE_CTRL_DEPTH);
572     }
573 
574     /* Find parent method to get method caller namepath */
575 
576     CallerOp = Op->Asl.Parent;
577     while (CallerOp &&
578         (CallerOp->Asl.ParseOpcode != PARSEOP_METHOD))
579     {
580         CallerOp = CallerOp->Asl.Parent;
581     }
582 
583     /* There is no parent method for External() statements */
584 
585     if (!CallerOp)
586     {
587         return (AE_OK);
588     }
589 
590     CallerFullPathname = AcpiNsGetNormalizedPathname (
591         CallerOp->Asl.Node, TRUE);
592 
593     FlPrintFile (ASL_FILE_XREF_OUTPUT,
594         "[%5u]     %-40s Invocation path: %s\n",
595         Op->Asl.LogicalLineNumber, CallerFullPathname,
596         Op->Asl.ExternalName);
597 
598     ACPI_FREE (CallerFullPathname);
599     XrefInfo->ThisMethodInvocations++;
600     return (AE_OK);
601 }
602 
603 
604 /*
605  * Part 3 of the cross reference file. This part emits the names of each
606  * non-predefined method in the namespace (user methods), along with the
607  * names of each control method that references that method.
608  */
609 
610 /*******************************************************************************
611  *
612  * FUNCTION:    OtXrefWalkPart3
613  *
614  * PARAMETERS:  ASL_WALK_CALLBACK
615  *
616  * RETURN:      Status
617  *
618  * DESCRIPTION: Cross-reference part 3. references to objects other than
619  *              control methods.
620  *
621  ******************************************************************************/
622 
623 static ACPI_STATUS
624 OtXrefWalkPart3 (
625     ACPI_PARSE_OBJECT       *Op,
626     UINT32                  Level,
627     void                    *Context)
628 {
629     ASL_XREF_INFO           *XrefInfo = (ASL_XREF_INFO *) Context;
630     ACPI_NAMESPACE_NODE     *Node;
631     char                    *ParentPath;
632     const ACPI_OPCODE_INFO  *OpInfo;
633 
634 
635     /* Ignore method declarations */
636 
637     if (!Op->Asl.Node ||
638         (Op->Asl.ParseOpcode == PARSEOP_METHOD))
639     {
640         return (AE_OK);
641     }
642 
643     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
644     if (!(OpInfo->Class & AML_CLASS_NAMED_OBJECT))
645     {
646         return (AE_OK);
647     }
648 
649     /* Only care about named object creation opcodes */
650 
651     if ((Op->Asl.ParseOpcode != PARSEOP_NAME) &&
652         (Op->Asl.ParseOpcode != PARSEOP_DEVICE) &&
653         (Op->Asl.ParseOpcode != PARSEOP_MUTEX) &&
654         (Op->Asl.ParseOpcode != PARSEOP_OPERATIONREGION) &&
655         (Op->Asl.ParseOpcode != PARSEOP_FIELD) &&
656         (Op->Asl.ParseOpcode != PARSEOP_EVENT))
657     {
658         return (AE_OK);
659     }
660 
661     /* Ignore predefined names */
662 
663     if (Op->Asl.Node->Name.Ascii[0] == '_')
664     {
665         return (AE_OK);
666     }
667 
668     Node = Op->Asl.Node;
669     ParentPath = AcpiNsGetNormalizedPathname (Node, TRUE);
670 
671     FlPrintFile (ASL_FILE_XREF_OUTPUT,
672         "\n[%5u]  %-40s %s Declaration\n",
673         Op->Asl.LogicalLineNumber, ParentPath,
674         AcpiUtGetTypeName (Node->Type));
675 
676     XrefInfo->MethodOp = Op;
677     XrefInfo->ThisObjectReferences = 0;
678     XrefInfo->TotalObjects = 0;
679 
680     (void) TrWalkParseTree (Gbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD,
681         OtXrefAnalysisWalkPart3, NULL, XrefInfo);
682 
683     if (!XrefInfo->ThisObjectReferences)
684     {
685         FlPrintFile (ASL_FILE_XREF_OUTPUT,
686             "            Zero references to this object in this module\n");
687         XrefInfo->TotalUnreferencedObjects++;
688     }
689     else
690     {
691         FlPrintFile (ASL_FILE_XREF_OUTPUT,
692             "            %u references to this object in this module\n",
693             XrefInfo->ThisObjectReferences, ParentPath);
694     }
695 
696     return (AE_OK);
697 }
698 
699 
700 /*******************************************************************************
701  *
702  * FUNCTION:    OtXrefAnalysisWalkPart3
703  *
704  * PARAMETERS:  ASL_WALK_CALLBACK
705  *
706  * RETURN:      Status
707  *
708  * DESCRIPTION: Secondary walk for cross-reference part 3.
709  *
710  ******************************************************************************/
711 
712 static ACPI_STATUS
713 OtXrefAnalysisWalkPart3 (
714     ACPI_PARSE_OBJECT       *Op,
715     UINT32                  Level,
716     void                    *Context)
717 {
718     ASL_XREF_INFO           *XrefInfo = (ASL_XREF_INFO *) Context;
719     char                    *CallerFullPathname;
720     ACPI_PARSE_OBJECT       *CallerOp;
721     const char              *Operator;
722 
723 
724     if (!Op->Asl.Node)
725     {
726         return (AE_OK);
727     }
728 
729     XrefInfo->TotalObjects++;
730 
731     /* Ignore Op that actually defined the object */
732 
733     if (Op == XrefInfo->MethodOp)
734     {
735         return (AE_OK);
736     }
737 
738     /* Only interested in Ops that reference the target node */
739 
740     if (Op->Asl.Node != XrefInfo->MethodOp->Asl.Node)
741     {
742         return (AE_OK);
743     }
744 
745     /* Find parent "open scope" object to get method caller namepath */
746 
747     CallerOp = Op->Asl.Parent;
748     while (CallerOp &&
749         (CallerOp->Asl.ParseOpcode != PARSEOP_NAME) &&
750         (CallerOp->Asl.ParseOpcode != PARSEOP_METHOD) &&
751         (CallerOp->Asl.ParseOpcode != PARSEOP_DEVICE) &&
752         (CallerOp->Asl.ParseOpcode != PARSEOP_POWERRESOURCE) &&
753         (CallerOp->Asl.ParseOpcode != PARSEOP_PROCESSOR) &&
754         (CallerOp->Asl.ParseOpcode != PARSEOP_THERMALZONE))
755     {
756         CallerOp = CallerOp->Asl.Parent;
757     }
758 
759     /* There are some special cases for the oddball operators */
760 
761     if (CallerOp)
762     {
763         CallerFullPathname = AcpiNsGetNormalizedPathname (
764             CallerOp->Asl.Node, TRUE);
765     }
766     else
767     {
768         CallerFullPathname = "<root>";
769     }
770 
771     if (CallerOp == XrefInfo->CurrentMethodOp)
772     {
773         return (AE_OK);
774     }
775 
776     if (Op->Asl.ParseOpcode == PARSEOP_SCOPE)
777     {
778         Operator = "Scope";
779 
780     }
781     else if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_ALIAS)
782     {
783         Operator = "Alias";
784     }
785     else if (!CallerOp)
786     {
787         Operator = "ModLevel";
788     }
789     else
790     {
791         Operator = AcpiUtGetTypeName (CallerOp->Asl.Node->Type);
792     }
793 
794     FlPrintFile (ASL_FILE_XREF_OUTPUT,
795         "[%5u]     %-40s %-8s via path: %s, Operator: %s\n",
796         Op->Asl.LogicalLineNumber,
797         CallerFullPathname,
798         Operator,
799         Op->Asl.ExternalName,
800         Op->Asl.Parent->Asl.ParseOpName);
801 
802     if (!CallerOp)
803     {
804         CallerOp = ACPI_TO_POINTER (0xFFFFFFFF);
805     }
806 
807     XrefInfo->CurrentMethodOp = CallerOp;
808     XrefInfo->ThisObjectReferences++;
809     return (AE_OK);
810 }
811