1 /******************************************************************************
2 *
3 * Module Name: aslxrefout.c - support for optional cross-reference file
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2022, 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 MERCHANTABILITY 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
OtPrintHeaders(char * Message)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
OtCreateXrefFile(void)135 OtCreateXrefFile (
136 void)
137 {
138 ASL_XREF_INFO XrefInfo;
139
140
141 /* Build cross-reference output file if requested */
142
143 if (!AslGbl_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 (AslGbl_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 (AslGbl_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
OtXrefWalkPart1(ACPI_PARSE_OBJECT * Op,UINT32 Level,ASL_METHOD_INFO * MethodInfo)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
256 /* Find all objects referenced by this method */
257
258 Status = TrWalkParseTree (MethodInfo->Op, ASL_WALK_VISIT_DOWNWARD,
259 OtXrefAnalysisWalkPart1, NULL, MethodInfo);
260
261 if (Status == AE_CTRL_TERMINATE)
262 {
263 ParentPath = AcpiNsGetNormalizedPathname (Node, TRUE);
264
265 FlPrintFile (ASL_FILE_XREF_OUTPUT, " %-40s %s",
266 ParentPath, AcpiUtGetTypeName (Node->Type));
267 ACPI_FREE (ParentPath);
268
269 switch (Node->Type)
270 {
271 /* Handle externals */
272
273 case ACPI_TYPE_ANY:
274 case ACPI_TYPE_FIELD_UNIT:
275
276 FlPrintFile (ASL_FILE_XREF_OUTPUT, " <External Object>");
277 break;
278
279 case ACPI_TYPE_INTEGER:
280
281 FlPrintFile (ASL_FILE_XREF_OUTPUT, " %8.8X%8.8X",
282 ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer));
283 break;
284
285 case ACPI_TYPE_METHOD:
286
287 FlPrintFile (ASL_FILE_XREF_OUTPUT, " Invocation (%u args)",
288 Node->ArgCount);
289 break;
290
291 case ACPI_TYPE_BUFFER_FIELD:
292
293 NextOp = Node->Op; /* Create Buffer Field Op */
294 switch (NextOp->Asl.ParseOpcode)
295 {
296 case PARSEOP_CREATEBITFIELD:
297 Length = 1;
298 break;
299
300 case PARSEOP_CREATEBYTEFIELD:
301 Length = 8;
302 break;
303
304 case PARSEOP_CREATEWORDFIELD:
305 Length = 16;
306 break;
307
308 case PARSEOP_CREATEDWORDFIELD:
309 Length = 32;
310 break;
311
312 case PARSEOP_CREATEQWORDFIELD:
313 Length = 64;
314 break;
315
316 default:
317 Length = 0;
318 break;
319 }
320
321 NextOp = NextOp->Asl.Child; /* Buffer name */
322
323 if (!NextOp->Asl.ExternalName)
324 {
325 FlPrintFile (ASL_FILE_XREF_OUTPUT, " in Arg/Local");
326 }
327 else
328 {
329 ParentPath = AcpiNsGetNormalizedPathname (
330 NextOp->Asl.Node, TRUE);
331
332 FlPrintFile (ASL_FILE_XREF_OUTPUT, " (%.2u bit) in Buffer %s",
333 Length, ParentPath);
334 ACPI_FREE (ParentPath);
335 }
336 break;
337
338 case ACPI_TYPE_LOCAL_REGION_FIELD:
339
340 NextOp = Node->Op;
341 FieldOp = NextOp->Asl.Parent;
342 NextOp = FieldOp->Asl.Child;
343
344 ParentPath = AcpiNsGetNormalizedPathname (
345 NextOp->Asl.Node, TRUE);
346
347 FlPrintFile (ASL_FILE_XREF_OUTPUT, " (%.2u bit) in Region %s",
348 (UINT32) Node->Op->Asl.Child->Asl.Value.Integer,
349 ParentPath);
350 ACPI_FREE (ParentPath);
351
352 if (FieldOp->Asl.ParseOpcode == PARSEOP_FIELD)
353 {
354 Node = NextOp->Asl.Node; /* Region node */
355 NextOp = Node->Op; /* PARSEOP_REGION */
356 NextOp = NextOp->Asl.Child; /* Region name */
357 NextOp = NextOp->Asl.Next;
358
359 /* Get region space/addr/len? */
360
361 FlPrintFile (ASL_FILE_XREF_OUTPUT, " (%s)",
362 AcpiUtGetRegionName ((UINT8)
363 NextOp->Asl.Value.Integer));
364 }
365 break;
366
367 default:
368 break;
369 }
370
371 FlPrintFile (ASL_FILE_XREF_OUTPUT, "\n");
372 }
373 break;
374
375 case PARSEOP_METHOD:
376
377 ParentPath = AcpiNsGetNormalizedPathname (Op->Asl.Node, TRUE);
378
379 FlPrintFile (ASL_FILE_XREF_OUTPUT,
380 "\n[%5u] %-40s %s Declaration (%u args)\n",
381 Op->Asl.LogicalLineNumber, ParentPath,
382 AcpiUtGetTypeName (Op->Asl.Node->Type), Op->Asl.Node->ArgCount);
383
384 ACPI_FREE (ParentPath);
385 break;
386
387 default:
388 break;
389 }
390 }
391
392
393 /*******************************************************************************
394 *
395 * FUNCTION: OtXrefAnalysisWalkPart1
396 *
397 * PARAMETERS: ASL_WALK_CALLBACK
398 *
399 * RETURN: Status
400 *
401 * DESCRIPTION: Secondary walk for cross-reference part 1.
402 *
403 ******************************************************************************/
404
405 static ACPI_STATUS
OtXrefAnalysisWalkPart1(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)406 OtXrefAnalysisWalkPart1 (
407 ACPI_PARSE_OBJECT *Op,
408 UINT32 Level,
409 void *Context)
410 {
411 ASL_METHOD_INFO *MethodInfo = (ASL_METHOD_INFO *) Context;
412 ACPI_PARSE_OBJECT *Next;
413
414
415 /* Only interested in name string Ops -- ignore all others */
416
417 if ((Op->Asl.ParseOpcode != PARSEOP_NAMESEG) &&
418 (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) &&
419 (Op->Asl.ParseOpcode != PARSEOP_METHODCALL))
420 {
421 return (AE_OK);
422 }
423
424 /* No node means a locally declared object -- ignore */
425
426 if (!Op->Asl.Node)
427 {
428 return (AE_OK);
429 }
430
431 /* When we encounter the source Op, we are done */
432
433 Next = MethodInfo->CurrentOp;
434 if (Next == Op)
435 {
436 return (AE_CTRL_TERMINATE);
437 }
438
439 /* If we have a name match, this Op is a duplicate */
440
441 if ((Next->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
442 (Next->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
443 (Next->Asl.ParseOpcode == PARSEOP_METHODCALL))
444 {
445 if (!strcmp (Op->Asl.ExternalName, Next->Asl.ExternalName))
446 {
447 return (AE_ALREADY_EXISTS);
448 }
449 }
450
451 return (AE_OK);
452 }
453
454
455 /*
456 * Part 2 of the cross reference file. This part emits the names of each
457 * non-predefined method in the namespace (user methods), along with the
458 * names of each control method that references that method.
459 */
460
461 /*******************************************************************************
462 *
463 * FUNCTION: OtXrefWalkPart2
464 *
465 * PARAMETERS: ASL_WALK_CALLBACK
466 *
467 * RETURN: Status
468 *
469 * DESCRIPTION: For each control method in the namespace, we will re-walk the
470 * namespace to find each and every invocation of that control
471 * method. Brute force, but does not matter, even for large
472 * namespaces. Ignore predefined names (start with underscore).
473 *
474 ******************************************************************************/
475
476 static ACPI_STATUS
OtXrefWalkPart2(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)477 OtXrefWalkPart2 (
478 ACPI_PARSE_OBJECT *Op,
479 UINT32 Level,
480 void *Context)
481 {
482 ASL_XREF_INFO *XrefInfo = (ASL_XREF_INFO *) Context;
483 ACPI_NAMESPACE_NODE *Node;
484 char *ParentPath;
485
486
487 /* Looking for Method Declaration Ops only */
488
489 if (!Op->Asl.Node ||
490 (Op->Asl.ParseOpcode != PARSEOP_METHOD))
491 {
492 return (AE_OK);
493 }
494
495 /* Ignore predefined names */
496
497 if (Op->Asl.Node->Name.Ascii[0] == '_')
498 {
499 XrefInfo->TotalPredefinedMethods++;
500 return (AE_OK);
501 }
502
503 Node = Op->Asl.Node;
504 ParentPath = AcpiNsGetNormalizedPathname (Node, TRUE);
505
506 FlPrintFile (ASL_FILE_XREF_OUTPUT,
507 "\n[%5u] %-40s %s Declaration (%u args)\n",
508 Op->Asl.LogicalLineNumber, ParentPath,
509 AcpiUtGetTypeName (Node->Type), Node->ArgCount);
510
511 XrefInfo->TotalUserMethods++;
512 XrefInfo->ThisMethodInvocations = 0;
513 XrefInfo->MethodOp = Op;
514
515 (void) TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD,
516 OtXrefAnalysisWalkPart2, NULL, XrefInfo);
517
518 if (!XrefInfo->ThisMethodInvocations)
519 {
520 FlPrintFile (ASL_FILE_XREF_OUTPUT,
521 " Zero invocations of this method in this module\n");
522 XrefInfo->TotalUnreferenceUserMethods++;
523 }
524 else
525 {
526 FlPrintFile (ASL_FILE_XREF_OUTPUT,
527 " %u invocations of method %s in this module\n",
528 XrefInfo->ThisMethodInvocations, ParentPath);
529 }
530
531 ACPI_FREE (ParentPath);
532 return (AE_OK);
533 }
534
535
536 /*******************************************************************************
537 *
538 * FUNCTION: OtXrefAnalysisWalkPart2
539 *
540 * PARAMETERS: ASL_WALK_CALLBACK
541 *
542 * RETURN: Status
543 *
544 * DESCRIPTION: For every Op that is a method invocation, emit a reference
545 * line if the Op is invoking the target method.
546 *
547 ******************************************************************************/
548
549 static ACPI_STATUS
OtXrefAnalysisWalkPart2(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)550 OtXrefAnalysisWalkPart2 (
551 ACPI_PARSE_OBJECT *Op,
552 UINT32 Level,
553 void *Context)
554 {
555 ASL_XREF_INFO *XrefInfo = (ASL_XREF_INFO *) Context;
556 ACPI_PARSE_OBJECT *CallerOp;
557 char *CallerFullPathname;
558
559
560 /* Looking for MethodCall Ops only */
561
562 if (!Op->Asl.Node ||
563 (Op->Asl.ParseOpcode != PARSEOP_METHODCALL))
564 {
565 return (AE_OK);
566 }
567
568 /* If not a match to the target method, we are done */
569
570 if (Op->Asl.Node != XrefInfo->MethodOp->Asl.Node)
571 {
572 return (AE_CTRL_DEPTH);
573 }
574
575 /* Find parent method to get method caller namepath */
576
577 CallerOp = Op->Asl.Parent;
578 while (CallerOp &&
579 (CallerOp->Asl.ParseOpcode != PARSEOP_METHOD))
580 {
581 CallerOp = CallerOp->Asl.Parent;
582 }
583
584 /* There is no parent method for External() statements */
585
586 if (!CallerOp)
587 {
588 return (AE_OK);
589 }
590
591 CallerFullPathname = AcpiNsGetNormalizedPathname (
592 CallerOp->Asl.Node, TRUE);
593
594 FlPrintFile (ASL_FILE_XREF_OUTPUT,
595 "[%5u] %-40s Invocation path: %s\n",
596 Op->Asl.LogicalLineNumber, CallerFullPathname,
597 Op->Asl.ExternalName);
598
599 ACPI_FREE (CallerFullPathname);
600 XrefInfo->ThisMethodInvocations++;
601 return (AE_OK);
602 }
603
604
605 /*
606 * Part 3 of the cross reference file. This part emits the names of each
607 * non-predefined method in the namespace (user methods), along with the
608 * names of each control method that references that method.
609 */
610
611 /*******************************************************************************
612 *
613 * FUNCTION: OtXrefWalkPart3
614 *
615 * PARAMETERS: ASL_WALK_CALLBACK
616 *
617 * RETURN: Status
618 *
619 * DESCRIPTION: Cross-reference part 3. references to objects other than
620 * control methods.
621 *
622 ******************************************************************************/
623
624 static ACPI_STATUS
OtXrefWalkPart3(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)625 OtXrefWalkPart3 (
626 ACPI_PARSE_OBJECT *Op,
627 UINT32 Level,
628 void *Context)
629 {
630 ASL_XREF_INFO *XrefInfo = (ASL_XREF_INFO *) Context;
631 ACPI_NAMESPACE_NODE *Node;
632 char *ParentPath;
633 const ACPI_OPCODE_INFO *OpInfo;
634
635
636 /* Ignore method declarations */
637
638 if (!Op->Asl.Node ||
639 (Op->Asl.ParseOpcode == PARSEOP_METHOD))
640 {
641 return (AE_OK);
642 }
643
644 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
645 if (!(OpInfo->Class & AML_CLASS_NAMED_OBJECT))
646 {
647 return (AE_OK);
648 }
649
650 /* Only care about named object creation opcodes */
651
652 if ((Op->Asl.ParseOpcode != PARSEOP_NAME) &&
653 (Op->Asl.ParseOpcode != PARSEOP_DEVICE) &&
654 (Op->Asl.ParseOpcode != PARSEOP_MUTEX) &&
655 (Op->Asl.ParseOpcode != PARSEOP_OPERATIONREGION) &&
656 (Op->Asl.ParseOpcode != PARSEOP_FIELD) &&
657 (Op->Asl.ParseOpcode != PARSEOP_EVENT))
658 {
659 return (AE_OK);
660 }
661
662 /* Ignore predefined names */
663
664 if (Op->Asl.Node->Name.Ascii[0] == '_')
665 {
666 return (AE_OK);
667 }
668
669 Node = Op->Asl.Node;
670 ParentPath = AcpiNsGetNormalizedPathname (Node, TRUE);
671
672 FlPrintFile (ASL_FILE_XREF_OUTPUT,
673 "\n[%5u] %-40s %s Declaration\n",
674 Op->Asl.LogicalLineNumber, ParentPath,
675 AcpiUtGetTypeName (Node->Type));
676 ACPI_FREE (ParentPath);
677
678 XrefInfo->MethodOp = Op;
679 XrefInfo->ThisObjectReferences = 0;
680 XrefInfo->TotalObjects = 0;
681
682 (void) TrWalkParseTree (AslGbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD,
683 OtXrefAnalysisWalkPart3, NULL, XrefInfo);
684
685 if (!XrefInfo->ThisObjectReferences)
686 {
687 FlPrintFile (ASL_FILE_XREF_OUTPUT,
688 " Zero references to this object in this module\n");
689 XrefInfo->TotalUnreferencedObjects++;
690 }
691 else
692 {
693 FlPrintFile (ASL_FILE_XREF_OUTPUT,
694 " %u references to this object in this module [%s]\n",
695 XrefInfo->ThisObjectReferences, ParentPath);
696 }
697
698 return (AE_OK);
699 }
700
701
702 /*******************************************************************************
703 *
704 * FUNCTION: OtXrefAnalysisWalkPart3
705 *
706 * PARAMETERS: ASL_WALK_CALLBACK
707 *
708 * RETURN: Status
709 *
710 * DESCRIPTION: Secondary walk for cross-reference part 3.
711 *
712 ******************************************************************************/
713
714 static ACPI_STATUS
OtXrefAnalysisWalkPart3(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)715 OtXrefAnalysisWalkPart3 (
716 ACPI_PARSE_OBJECT *Op,
717 UINT32 Level,
718 void *Context)
719 {
720 ASL_XREF_INFO *XrefInfo = (ASL_XREF_INFO *) Context;
721 char *CallerFullPathname = NULL;
722 ACPI_PARSE_OBJECT *CallerOp;
723 const char *Operator;
724
725
726 if (!Op->Asl.Node)
727 {
728 return (AE_OK);
729 }
730
731 XrefInfo->TotalObjects++;
732
733 /* Ignore Op that actually defined the object */
734
735 if (Op == XrefInfo->MethodOp)
736 {
737 return (AE_OK);
738 }
739
740 /* Only interested in Ops that reference the target node */
741
742 if (Op->Asl.Node != XrefInfo->MethodOp->Asl.Node)
743 {
744 return (AE_OK);
745 }
746
747 /* Find parent "open scope" object to get method caller namepath */
748
749 CallerOp = Op->Asl.Parent;
750 while (CallerOp &&
751 (CallerOp->Asl.ParseOpcode != PARSEOP_NAME) &&
752 (CallerOp->Asl.ParseOpcode != PARSEOP_METHOD) &&
753 (CallerOp->Asl.ParseOpcode != PARSEOP_DEVICE) &&
754 (CallerOp->Asl.ParseOpcode != PARSEOP_POWERRESOURCE) &&
755 (CallerOp->Asl.ParseOpcode != PARSEOP_PROCESSOR) &&
756 (CallerOp->Asl.ParseOpcode != PARSEOP_THERMALZONE))
757 {
758 CallerOp = CallerOp->Asl.Parent;
759 }
760
761 if (CallerOp == XrefInfo->CurrentMethodOp)
762 {
763 return (AE_OK);
764 }
765
766 /* Null CallerOp means the caller is at the namespace root */
767
768 if (CallerOp)
769 {
770 CallerFullPathname = AcpiNsGetNormalizedPathname (
771 CallerOp->Asl.Node, TRUE);
772 }
773
774 /* There are some special cases for the oddball operators */
775
776 if (Op->Asl.ParseOpcode == PARSEOP_SCOPE)
777 {
778 Operator = "Scope";
779 }
780 else if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_ALIAS)
781 {
782 Operator = "Alias";
783 }
784 else if (!CallerOp)
785 {
786 Operator = "ModLevel";
787 }
788 else
789 {
790 Operator = AcpiUtGetTypeName (CallerOp->Asl.Node->Type);
791 }
792
793 FlPrintFile (ASL_FILE_XREF_OUTPUT,
794 "[%5u] %-40s %-8s via path: %s, Operator: %s\n",
795 Op->Asl.LogicalLineNumber,
796 CallerFullPathname ? CallerFullPathname : "<root>",
797 Operator,
798 Op->Asl.ExternalName,
799 Op->Asl.Parent->Asl.ParseOpName);
800
801 if (!CallerOp)
802 {
803 CallerOp = ACPI_TO_POINTER (0xFFFFFFFF);
804 }
805
806 if (CallerFullPathname)
807 {
808 ACPI_FREE (CallerFullPathname);
809 }
810
811 XrefInfo->CurrentMethodOp = CallerOp;
812 XrefInfo->ThisObjectReferences++;
813 return (AE_OK);
814 }
815