1 /******************************************************************************
2  *
3  * Module Name: adwalk - Application-level disassembler parse tree walk routines
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 "acpi.h"
45 #include "accommon.h"
46 #include "acparser.h"
47 #include "amlcode.h"
48 #include "acdisasm.h"
49 #include "acdispat.h"
50 #include "acnamesp.h"
51 #include "acapps.h"
52 
53 
54 #define _COMPONENT          ACPI_TOOLS
55         ACPI_MODULE_NAME    ("adwalk")
56 
57 /*
58  * aslmap - opcode mappings and reserved method names
59  */
60 ACPI_OBJECT_TYPE
61 AslMapNamedOpcodeToDataType (
62     UINT16                  Opcode);
63 
64 /* Local prototypes */
65 
66 static ACPI_STATUS
67 AcpiDmFindOrphanDescending (
68     ACPI_PARSE_OBJECT       *Op,
69     UINT32                  Level,
70     void                    *Context);
71 
72 static ACPI_STATUS
73 AcpiDmDumpDescending (
74     ACPI_PARSE_OBJECT       *Op,
75     UINT32                  Level,
76     void                    *Context);
77 
78 static ACPI_STATUS
79 AcpiDmXrefDescendingOp (
80     ACPI_PARSE_OBJECT       *Op,
81     UINT32                  Level,
82     void                    *Context);
83 
84 static ACPI_STATUS
85 AcpiDmCommonAscendingOp (
86     ACPI_PARSE_OBJECT       *Op,
87     UINT32                  Level,
88     void                    *Context);
89 
90 static ACPI_STATUS
91 AcpiDmLoadDescendingOp (
92     ACPI_PARSE_OBJECT       *Op,
93     UINT32                  Level,
94     void                    *Context);
95 
96 static UINT32
97 AcpiDmInspectPossibleArgs (
98     UINT32                  CurrentOpArgCount,
99     UINT32                  TargetCount,
100     ACPI_PARSE_OBJECT       *Op);
101 
102 static ACPI_STATUS
103 AcpiDmResourceDescendingOp (
104     ACPI_PARSE_OBJECT       *Op,
105     UINT32                  Level,
106     void                    *Context);
107 
108 
109 /*******************************************************************************
110  *
111  * FUNCTION:    AcpiDmDumpTree
112  *
113  * PARAMETERS:  Origin              - Starting object
114  *
115  * RETURN:      None
116  *
117  * DESCRIPTION: Parse tree walk to format and output the nodes
118  *
119  ******************************************************************************/
120 
121 void
122 AcpiDmDumpTree (
123     ACPI_PARSE_OBJECT       *Origin)
124 {
125     ACPI_OP_WALK_INFO       Info;
126 
127 
128     if (!Origin)
129     {
130         return;
131     }
132 
133     AcpiOsPrintf ("/*\nAML Parse Tree\n\n");
134     Info.Flags = 0;
135     Info.Count = 0;
136     Info.Level = 0;
137     Info.WalkState = NULL;
138 
139     AcpiDmWalkParseTree (Origin, AcpiDmDumpDescending, NULL, &Info);
140     AcpiOsPrintf ("*/\n\n");
141 }
142 
143 
144 /*******************************************************************************
145  *
146  * FUNCTION:    AcpiDmFindOrphanMethods
147  *
148  * PARAMETERS:  Origin              - Starting object
149  *
150  * RETURN:      None
151  *
152  * DESCRIPTION: Parse tree walk to find "orphaned" method invocations -- methods
153  *              that are not resolved in the namespace
154  *
155  ******************************************************************************/
156 
157 void
158 AcpiDmFindOrphanMethods (
159     ACPI_PARSE_OBJECT       *Origin)
160 {
161     ACPI_OP_WALK_INFO       Info;
162 
163 
164     if (!Origin)
165     {
166         return;
167     }
168 
169     Info.Flags = 0;
170     Info.Level = 0;
171     Info.WalkState = NULL;
172 
173     AcpiDmWalkParseTree (Origin, AcpiDmFindOrphanDescending, NULL, &Info);
174 }
175 
176 
177 /*******************************************************************************
178  *
179  * FUNCTION:    AcpiDmFinishNamespaceLoad
180  *
181  * PARAMETERS:  ParseTreeRoot       - Root of the parse tree
182  *              NamespaceRoot       - Root of the internal namespace
183  *              OwnerId             - OwnerId of the table to be disassembled
184  *
185  * RETURN:      None
186  *
187  * DESCRIPTION: Load all namespace items that are created within control
188  *              methods. Used before namespace cross reference
189  *
190  ******************************************************************************/
191 
192 void
193 AcpiDmFinishNamespaceLoad (
194     ACPI_PARSE_OBJECT       *ParseTreeRoot,
195     ACPI_NAMESPACE_NODE     *NamespaceRoot,
196     ACPI_OWNER_ID           OwnerId)
197 {
198     ACPI_STATUS             Status;
199     ACPI_OP_WALK_INFO       Info;
200     ACPI_WALK_STATE         *WalkState;
201 
202 
203     if (!ParseTreeRoot)
204     {
205         return;
206     }
207 
208     /* Create and initialize a new walk state */
209 
210     WalkState = AcpiDsCreateWalkState (OwnerId, ParseTreeRoot, NULL, NULL);
211     if (!WalkState)
212     {
213         return;
214     }
215 
216     Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type,
217         WalkState);
218     if (ACPI_FAILURE (Status))
219     {
220         return;
221     }
222 
223     Info.Flags = 0;
224     Info.Level = 0;
225     Info.WalkState = WalkState;
226 
227     AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmLoadDescendingOp,
228         AcpiDmCommonAscendingOp, &Info);
229     ACPI_FREE (WalkState);
230 }
231 
232 
233 /*******************************************************************************
234  *
235  * FUNCTION:    AcpiDmCrossReferenceNamespace
236  *
237  * PARAMETERS:  ParseTreeRoot       - Root of the parse tree
238  *              NamespaceRoot       - Root of the internal namespace
239  *              OwnerId             - OwnerId of the table to be disassembled
240  *
241  * RETURN:      None
242  *
243  * DESCRIPTION: Cross reference the namespace to create externals
244  *
245  ******************************************************************************/
246 
247 void
248 AcpiDmCrossReferenceNamespace (
249     ACPI_PARSE_OBJECT       *ParseTreeRoot,
250     ACPI_NAMESPACE_NODE     *NamespaceRoot,
251     ACPI_OWNER_ID           OwnerId)
252 {
253     ACPI_STATUS             Status;
254     ACPI_OP_WALK_INFO       Info;
255     ACPI_WALK_STATE         *WalkState;
256 
257 
258     if (!ParseTreeRoot)
259     {
260         return;
261     }
262 
263     /* Create and initialize a new walk state */
264 
265     WalkState = AcpiDsCreateWalkState (OwnerId, ParseTreeRoot, NULL, NULL);
266     if (!WalkState)
267     {
268         return;
269     }
270 
271     Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type,
272         WalkState);
273     if (ACPI_FAILURE (Status))
274     {
275         return;
276     }
277 
278     Info.Flags = 0;
279     Info.Level = 0;
280     Info.WalkState = WalkState;
281 
282     AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmXrefDescendingOp,
283         AcpiDmCommonAscendingOp, &Info);
284     ACPI_FREE (WalkState);
285 }
286 
287 
288 /*******************************************************************************
289  *
290  * FUNCTION:    AcpiDmConvertResourceIndexes
291  *
292  * PARAMETERS:  ParseTreeRoot       - Root of the parse tree
293  *              NamespaceRoot       - Root of the internal namespace
294  *
295  * RETURN:      None
296  *
297  * DESCRIPTION: Convert fixed-offset references to resource descriptors to
298  *              symbolic references. Should only be called after namespace has
299  *              been cross referenced.
300  *
301  ******************************************************************************/
302 
303 void
304 AcpiDmConvertResourceIndexes (
305     ACPI_PARSE_OBJECT       *ParseTreeRoot,
306     ACPI_NAMESPACE_NODE     *NamespaceRoot)
307 {
308     ACPI_STATUS             Status;
309     ACPI_OP_WALK_INFO       Info;
310     ACPI_WALK_STATE         *WalkState;
311 
312 
313     if (!ParseTreeRoot)
314     {
315         return;
316     }
317 
318     /* Create and initialize a new walk state */
319 
320     WalkState = AcpiDsCreateWalkState (0, ParseTreeRoot, NULL, NULL);
321     if (!WalkState)
322     {
323         return;
324     }
325 
326     Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type,
327         WalkState);
328     if (ACPI_FAILURE (Status))
329     {
330         return;
331     }
332 
333     Info.Flags = 0;
334     Info.Level = 0;
335     Info.WalkState = WalkState;
336 
337     AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmResourceDescendingOp,
338         AcpiDmCommonAscendingOp, &Info);
339     ACPI_FREE (WalkState);
340     return;
341 }
342 
343 
344 /*******************************************************************************
345  *
346  * FUNCTION:    AcpiDmDumpDescending
347  *
348  * PARAMETERS:  ASL_WALK_CALLBACK
349  *
350  * RETURN:      Status
351  *
352  * DESCRIPTION: Format and print contents of one parse Op.
353  *
354  ******************************************************************************/
355 
356 static ACPI_STATUS
357 AcpiDmDumpDescending (
358     ACPI_PARSE_OBJECT       *Op,
359     UINT32                  Level,
360     void                    *Context)
361 {
362     ACPI_OP_WALK_INFO       *Info = Context;
363     char                    *Path;
364 
365 
366     if (!Op)
367     {
368         return (AE_OK);
369     }
370 
371     /* Most of the information (count, level, name) here */
372 
373     Info->Count++;
374     AcpiOsPrintf ("% 5d [%2.2d] ", Info->Count, Level);
375     AcpiDmIndent (Level);
376     AcpiOsPrintf ("%-28s", AcpiPsGetOpcodeName (Op->Common.AmlOpcode));
377 
378     /* Extra info is helpful */
379 
380     switch (Op->Common.AmlOpcode)
381     {
382     case AML_BYTE_OP:
383 
384         AcpiOsPrintf ("%2.2X", (UINT32) Op->Common.Value.Integer);
385         break;
386 
387     case AML_WORD_OP:
388 
389         AcpiOsPrintf ("%4.4X", (UINT32) Op->Common.Value.Integer);
390         break;
391 
392     case AML_DWORD_OP:
393 
394         AcpiOsPrintf ("%8.8X", (UINT32) Op->Common.Value.Integer);
395         break;
396 
397     case AML_QWORD_OP:
398 
399         AcpiOsPrintf ("%8.8X%8.8X", ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
400         break;
401 
402     case AML_INT_NAMEPATH_OP:
403 
404         if (Op->Common.Value.String)
405         {
406             AcpiNsExternalizeName (ACPI_UINT32_MAX, Op->Common.Value.String,
407                 NULL, &Path);
408             AcpiOsPrintf ("%s %p", Path, Op->Common.Node);
409             ACPI_FREE (Path);
410         }
411         else
412         {
413             AcpiOsPrintf ("[NULL]");
414         }
415         break;
416 
417     case AML_NAME_OP:
418     case AML_METHOD_OP:
419     case AML_DEVICE_OP:
420     case AML_INT_NAMEDFIELD_OP:
421 
422         AcpiOsPrintf ("%4.4s", ACPI_CAST_PTR (char, &Op->Named.Name));
423         break;
424 
425     default:
426 
427         break;
428     }
429 
430     AcpiOsPrintf ("\n");
431     return (AE_OK);
432 }
433 
434 
435 /*******************************************************************************
436  *
437  * FUNCTION:    AcpiDmFindOrphanDescending
438  *
439  * PARAMETERS:  ASL_WALK_CALLBACK
440  *
441  * RETURN:      Status
442  *
443  * DESCRIPTION: Check namepath Ops for orphaned method invocations
444  *
445  * Note: Experimental.
446  *
447  ******************************************************************************/
448 
449 static ACPI_STATUS
450 AcpiDmFindOrphanDescending (
451     ACPI_PARSE_OBJECT       *Op,
452     UINT32                  Level,
453     void                    *Context)
454 {
455     const ACPI_OPCODE_INFO  *OpInfo;
456     ACPI_PARSE_OBJECT       *ChildOp;
457     ACPI_PARSE_OBJECT       *NextOp;
458     ACPI_PARSE_OBJECT       *ParentOp;
459     UINT32                  ArgCount;
460 
461 
462     if (!Op)
463     {
464         return (AE_OK);
465     }
466 
467     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
468 
469     switch (Op->Common.AmlOpcode)
470     {
471 #ifdef ACPI_UNDER_DEVELOPMENT
472     case AML_ADD_OP:
473 
474         ChildOp = Op->Common.Value.Arg;
475         if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
476             !ChildOp->Common.Node)
477         {
478             AcpiNsExternalizeName (ACPI_UINT32_MAX, ChildOp->Common.Value.String,
479                 NULL, &Path);
480             AcpiOsPrintf ("/* %-16s A-NAMEPATH: %s  */\n",
481                 Op->Common.AmlOpName, Path);
482             ACPI_FREE (Path);
483 
484             NextOp = Op->Common.Next;
485             if (!NextOp)
486             {
487                 /* This NamePath has no args, assume it is an integer */
488 
489                 AcpiDmAddOpToExternalList (ChildOp,
490                     ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
491                 return (AE_OK);
492             }
493 
494             ArgCount = AcpiDmInspectPossibleArgs (3, 1, NextOp);
495             AcpiOsPrintf ("/* A-CHILDREN: %u Actual %u */\n",
496                 ArgCount, AcpiDmCountChildren (Op));
497 
498             if (ArgCount < 1)
499             {
500                 /* One Arg means this is just a Store(Name,Target) */
501 
502                 AcpiDmAddOpToExternalList (ChildOp,
503                     ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
504                 return (AE_OK);
505             }
506 
507             AcpiDmAddOpToExternalList (ChildOp,
508                 ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0);
509         }
510         break;
511 #endif
512 
513     case AML_STORE_OP:
514 
515         ChildOp = Op->Common.Value.Arg;
516         if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
517             !ChildOp->Common.Node)
518         {
519             NextOp = Op->Common.Next;
520             if (!NextOp)
521             {
522                 /* This NamePath has no args, assume it is an integer */
523 
524                 AcpiDmAddOpToExternalList (ChildOp,
525                     ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
526                 return (AE_OK);
527             }
528 
529             ArgCount = AcpiDmInspectPossibleArgs (2, 1, NextOp);
530             if (ArgCount <= 1)
531             {
532                 /* One Arg means this is just a Store(Name,Target) */
533 
534                 AcpiDmAddOpToExternalList (ChildOp,
535                     ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
536                 return (AE_OK);
537             }
538 
539             AcpiDmAddOpToExternalList (ChildOp,
540                 ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0);
541         }
542         break;
543 
544     case AML_INT_NAMEPATH_OP:
545 
546         /* Must examine parent to see if this namepath is an argument */
547 
548         ParentOp = Op->Common.Parent;
549         OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode);
550 
551         if ((OpInfo->Class != AML_CLASS_EXECUTE) &&
552             (OpInfo->Class != AML_CLASS_CREATE) &&
553             (OpInfo->ObjectType != ACPI_TYPE_LOCAL_ALIAS) &&
554             (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) &&
555             !Op->Common.Node)
556         {
557             ArgCount = AcpiDmInspectPossibleArgs (0, 0, Op->Common.Next);
558 
559             /*
560              * Check if namepath is a predicate for if/while or lone parameter to
561              * a return.
562              */
563             if (ArgCount == 0)
564             {
565                 if (((ParentOp->Common.AmlOpcode == AML_IF_OP) ||
566                      (ParentOp->Common.AmlOpcode == AML_WHILE_OP) ||
567                      (ParentOp->Common.AmlOpcode == AML_RETURN_OP)) &&
568 
569                      /* And namepath is the first argument */
570                      (ParentOp->Common.Value.Arg == Op))
571                 {
572                     AcpiDmAddOpToExternalList (Op,
573                         Op->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
574                     break;
575                 }
576             }
577 
578             /*
579              * This is a standalone namestring (not a parameter to another
580              * operator) - it *must* be a method invocation, nothing else is
581              * grammatically possible.
582              */
583             AcpiDmAddOpToExternalList (Op,
584                 Op->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0);
585         }
586         break;
587 
588     default:
589 
590         break;
591     }
592 
593     return (AE_OK);
594 }
595 
596 
597 /*******************************************************************************
598  *
599  * FUNCTION:    AcpiDmLoadDescendingOp
600  *
601  * PARAMETERS:  ASL_WALK_CALLBACK
602  *
603  * RETURN:      Status
604  *
605  * DESCRIPTION: Descending handler for namespace control method object load
606  *
607  ******************************************************************************/
608 
609 static ACPI_STATUS
610 AcpiDmLoadDescendingOp (
611     ACPI_PARSE_OBJECT       *Op,
612     UINT32                  Level,
613     void                    *Context)
614 {
615     ACPI_OP_WALK_INFO       *Info = Context;
616     const ACPI_OPCODE_INFO  *OpInfo;
617     ACPI_WALK_STATE         *WalkState;
618     ACPI_OBJECT_TYPE        ObjectType;
619     ACPI_STATUS             Status;
620     char                    *Path = NULL;
621     ACPI_PARSE_OBJECT       *NextOp;
622     ACPI_NAMESPACE_NODE     *Node;
623     char                    FieldPath[5];
624     BOOLEAN                 PreDefined = FALSE;
625     UINT8                   PreDefineIndex = 0;
626 
627 
628     WalkState = Info->WalkState;
629     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
630     ObjectType = OpInfo->ObjectType;
631     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
632 
633     /* Only interested in operators that create new names */
634 
635     if (!(OpInfo->Flags & AML_NAMED) &&
636         !(OpInfo->Flags & AML_CREATE))
637     {
638         goto Exit;
639     }
640 
641     /* Get the NamePath from the appropriate place */
642 
643     if (OpInfo->Flags & AML_NAMED)
644     {
645         /* For all named operators, get the new name */
646 
647         Path = (char *) Op->Named.Path;
648 
649         if (!Path && Op->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP)
650         {
651             *ACPI_CAST_PTR (UINT32, &FieldPath[0]) = Op->Named.Name;
652             FieldPath[4] = 0;
653             Path = FieldPath;
654         }
655     }
656     else if (OpInfo->Flags & AML_CREATE)
657     {
658         /* New name is the last child */
659 
660         NextOp = Op->Common.Value.Arg;
661 
662         while (NextOp->Common.Next)
663         {
664             NextOp = NextOp->Common.Next;
665         }
666 
667         Path = NextOp->Common.Value.String;
668     }
669 
670     if (!Path)
671     {
672         goto Exit;
673     }
674 
675     /* Insert the name into the namespace */
676 
677     Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
678         ACPI_IMODE_LOAD_PASS2, ACPI_NS_DONT_OPEN_SCOPE,
679         WalkState, &Node);
680 
681     Op->Common.Node = Node;
682 
683     if (ACPI_SUCCESS (Status))
684     {
685         /* Check if it's a predefined node */
686 
687         while (AcpiGbl_PreDefinedNames[PreDefineIndex].Name)
688         {
689             if (ACPI_COMPARE_NAME (Node->Name.Ascii,
690                 AcpiGbl_PreDefinedNames[PreDefineIndex].Name))
691             {
692                 PreDefined = TRUE;
693                 break;
694             }
695 
696             PreDefineIndex++;
697         }
698 
699         /*
700          * Set node owner id if it satisfies all the following conditions:
701          * 1) Not a predefined node, _SB_ etc
702          * 2) Not the root node
703          * 3) Not a node created by Scope
704          */
705 
706         if (!PreDefined && Node != AcpiGbl_RootNode &&
707             Op->Common.AmlOpcode != AML_SCOPE_OP)
708         {
709             Node->OwnerId = WalkState->OwnerId;
710         }
711     }
712 
713 
714 Exit:
715 
716     if (AcpiNsOpensScope (ObjectType))
717     {
718         if (Op->Common.Node)
719         {
720             Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType,
721                 WalkState);
722             if (ACPI_FAILURE (Status))
723             {
724                 return (Status);
725             }
726         }
727     }
728 
729     return (AE_OK);
730 }
731 
732 
733 /*******************************************************************************
734  *
735  * FUNCTION:    AcpiDmXrefDescendingOp
736  *
737  * PARAMETERS:  ASL_WALK_CALLBACK
738  *
739  * RETURN:      Status
740  *
741  * DESCRIPTION: Descending handler for namespace cross reference
742  *
743  ******************************************************************************/
744 
745 static ACPI_STATUS
746 AcpiDmXrefDescendingOp (
747     ACPI_PARSE_OBJECT       *Op,
748     UINT32                  Level,
749     void                    *Context)
750 {
751     ACPI_OP_WALK_INFO       *Info = Context;
752     const ACPI_OPCODE_INFO  *OpInfo;
753     ACPI_WALK_STATE         *WalkState;
754     ACPI_OBJECT_TYPE        ObjectType;
755     ACPI_OBJECT_TYPE        ObjectType2;
756     ACPI_STATUS             Status;
757     char                    *Path = NULL;
758     ACPI_PARSE_OBJECT       *NextOp;
759     ACPI_NAMESPACE_NODE     *Node;
760     ACPI_OPERAND_OBJECT     *Object;
761     UINT32                  ParamCount = 0;
762     char                    *Pathname;
763 
764 
765     WalkState = Info->WalkState;
766     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
767     ObjectType = OpInfo->ObjectType;
768     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
769 
770     if ((!(OpInfo->Flags & AML_NAMED)) &&
771         (!(OpInfo->Flags & AML_CREATE)) &&
772         (Op->Common.AmlOpcode != AML_INT_NAMEPATH_OP) &&
773         (Op->Common.AmlOpcode != AML_NOTIFY_OP))
774     {
775         goto Exit;
776     }
777 
778 
779     /* Get the NamePath from the appropriate place */
780 
781     if (OpInfo->Flags & AML_NAMED)
782     {
783         /*
784          * Only these two operators (Alias, Scope) refer to an existing
785          * name, it is the first argument
786          */
787         if (Op->Common.AmlOpcode == AML_ALIAS_OP)
788         {
789             ObjectType = ACPI_TYPE_ANY;
790 
791             NextOp = Op->Common.Value.Arg;
792             NextOp = NextOp->Common.Value.Arg;
793             if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
794             {
795                 Path = NextOp->Common.Value.String;
796             }
797         }
798         else if (Op->Common.AmlOpcode == AML_SCOPE_OP)
799         {
800             Path = (char *) Op->Named.Path;
801         }
802     }
803     else if (OpInfo->Flags & AML_CREATE)
804     {
805         /* Referenced Buffer Name is the first child */
806 
807         ObjectType = ACPI_TYPE_BUFFER; /* Change from TYPE_BUFFER_FIELD */
808 
809         NextOp = Op->Common.Value.Arg;
810         if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
811         {
812             Path = NextOp->Common.Value.String;
813         }
814     }
815     else if (Op->Common.AmlOpcode == AML_NOTIFY_OP)
816     {
817         Path = Op->Common.Value.Arg->Asl.Value.String;
818     }
819     else
820     {
821         Path = Op->Common.Value.String;
822     }
823 
824     if (!Path)
825     {
826         goto Exit;
827     }
828 
829     /*
830      * Lookup the name in the namespace. Name must exist at this point, or it
831      * is an invalid reference.
832      *
833      * The namespace is also used as a lookup table for references to resource
834      * descriptors and the fields within them.
835      */
836     Node = NULL;
837     Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY,
838         ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
839         WalkState, &Node);
840     if (ACPI_SUCCESS (Status) && (Node->Flags & ANOBJ_IS_EXTERNAL))
841     {
842         /* Node was created by an External() statement */
843 
844         Status = AE_NOT_FOUND;
845     }
846 
847     if (ACPI_FAILURE (Status))
848     {
849         if (Status == AE_NOT_FOUND)
850         {
851             /*
852              * Add this symbol as an external declaration, except if the
853              * parent is a CondRefOf operator. For this operator, we do not
854              * need an external, nor do we want one, since this can cause
855              * disassembly problems if the symbol is actually a control
856              * method.
857              */
858             if (!(Op->Asl.Parent &&
859                 (Op->Asl.Parent->Asl.AmlOpcode == AML_COND_REF_OF_OP)))
860             {
861                 if (Node)
862                 {
863                     AcpiDmAddNodeToExternalList (Node,
864                         (UINT8) ObjectType, 0, 0);
865                 }
866                 else
867                 {
868                     AcpiDmAddOpToExternalList (Op, Path,
869                         (UINT8) ObjectType, 0, 0);
870                 }
871             }
872         }
873     }
874 
875     /*
876      * Found the node, but check if it came from an external table.
877      * Add it to external list. Note: Node->OwnerId == 0 indicates
878      * one of the built-in ACPI Names (_OS_ etc.) which can safely
879      * be ignored.
880      */
881     else if (Node->OwnerId &&
882             (WalkState->OwnerId != Node->OwnerId))
883     {
884         ObjectType2 = ObjectType;
885 
886         Object = AcpiNsGetAttachedObject (Node);
887         if (Object)
888         {
889             ObjectType2 = Object->Common.Type;
890             if (ObjectType2 == ACPI_TYPE_METHOD)
891             {
892                 ParamCount = Object->Method.ParamCount;
893             }
894         }
895 
896         Pathname = AcpiNsGetExternalPathname (Node);
897         if (!Pathname)
898         {
899             return (AE_NO_MEMORY);
900         }
901 
902         AcpiDmAddNodeToExternalList (Node, (UINT8) ObjectType2,
903             ParamCount, ACPI_EXT_RESOLVED_REFERENCE);
904 
905         ACPI_FREE (Pathname);
906         Op->Common.Node = Node;
907     }
908     else
909     {
910         Op->Common.Node = Node;
911     }
912 
913 
914 Exit:
915     /* Open new scope if necessary */
916 
917     if (AcpiNsOpensScope (ObjectType))
918     {
919         if (Op->Common.Node)
920         {
921             Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType,
922                 WalkState);
923             if (ACPI_FAILURE (Status))
924             {
925                 return (Status);
926             }
927         }
928     }
929 
930     return (AE_OK);
931 }
932 
933 
934 /*******************************************************************************
935  *
936  * FUNCTION:    AcpiDmResourceDescendingOp
937  *
938  * PARAMETERS:  ASL_WALK_CALLBACK
939  *
940  * RETURN:      None
941  *
942  * DESCRIPTION: Process one parse op during symbolic resource index conversion.
943  *
944  ******************************************************************************/
945 
946 static ACPI_STATUS
947 AcpiDmResourceDescendingOp (
948     ACPI_PARSE_OBJECT       *Op,
949     UINT32                  Level,
950     void                    *Context)
951 {
952     ACPI_OP_WALK_INFO       *Info = Context;
953     const ACPI_OPCODE_INFO  *OpInfo;
954     ACPI_WALK_STATE         *WalkState;
955     ACPI_OBJECT_TYPE        ObjectType;
956     ACPI_STATUS             Status;
957 
958 
959     WalkState = Info->WalkState;
960     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
961 
962     /* Open new scope if necessary */
963 
964     ObjectType = OpInfo->ObjectType;
965     if (AcpiNsOpensScope (ObjectType))
966     {
967         if (Op->Common.Node)
968         {
969 
970             Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType,
971                 WalkState);
972             if (ACPI_FAILURE (Status))
973             {
974                 return (Status);
975             }
976         }
977     }
978 
979     /*
980      * Check if this operator contains a reference to a resource descriptor.
981      * If so, convert the reference into a symbolic reference.
982      */
983     AcpiDmCheckResourceReference (Op, WalkState);
984     return (AE_OK);
985 }
986 
987 
988 /*******************************************************************************
989  *
990  * FUNCTION:    AcpiDmCommonAscendingOp
991  *
992  * PARAMETERS:  ASL_WALK_CALLBACK
993  *
994  * RETURN:      None
995  *
996  * DESCRIPTION: Ascending handler for combined parse/namespace walks. Closes
997  *              scope if necessary.
998  *
999  ******************************************************************************/
1000 
1001 static ACPI_STATUS
1002 AcpiDmCommonAscendingOp (
1003     ACPI_PARSE_OBJECT       *Op,
1004     UINT32                  Level,
1005     void                    *Context)
1006 {
1007     ACPI_OP_WALK_INFO       *Info = Context;
1008     const ACPI_OPCODE_INFO  *OpInfo;
1009     ACPI_OBJECT_TYPE        ObjectType;
1010 
1011 
1012     /* Close scope if necessary */
1013 
1014     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
1015     ObjectType = OpInfo->ObjectType;
1016     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
1017 
1018     if (AcpiNsOpensScope (ObjectType))
1019     {
1020         (void) AcpiDsScopeStackPop (Info->WalkState);
1021     }
1022 
1023     return (AE_OK);
1024 }
1025 
1026 
1027 /*******************************************************************************
1028  *
1029  * FUNCTION:    AcpiDmInspectPossibleArgs
1030  *
1031  * PARAMETERS:  CurrentOpArgCount   - Which arg of the current op was the
1032  *                                    possible method invocation found
1033  *              TargetCount         - Number of targets (0,1,2) for this op
1034  *              Op                  - Parse op
1035  *
1036  * RETURN:      Status
1037  *
1038  * DESCRIPTION: Examine following args and next ops for possible arguments
1039  *              for an unrecognized method invocation.
1040  *
1041  ******************************************************************************/
1042 
1043 static UINT32
1044 AcpiDmInspectPossibleArgs (
1045     UINT32                  CurrentOpArgCount,
1046     UINT32                  TargetCount,
1047     ACPI_PARSE_OBJECT       *Op)
1048 {
1049     const ACPI_OPCODE_INFO  *OpInfo;
1050     UINT32                  i;
1051     UINT32                  Last = 0;
1052     UINT32                  Lookahead;
1053 
1054 
1055     Lookahead = (ACPI_METHOD_NUM_ARGS + TargetCount) - CurrentOpArgCount;
1056 
1057     /* Lookahead for the maximum number of possible arguments */
1058 
1059     for (i = 0; i < Lookahead; i++)
1060     {
1061         if (!Op)
1062         {
1063             break;
1064         }
1065 
1066         OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
1067 
1068         /*
1069          * Any one of these operators is "very probably" not a method arg
1070          */
1071         if ((Op->Common.AmlOpcode == AML_STORE_OP) ||
1072             (Op->Common.AmlOpcode == AML_NOTIFY_OP))
1073         {
1074             break;
1075         }
1076 
1077         if ((OpInfo->Class != AML_CLASS_EXECUTE) &&
1078             (OpInfo->Class != AML_CLASS_CONTROL))
1079         {
1080             Last = i+1;
1081         }
1082 
1083         Op = Op->Common.Next;
1084     }
1085 
1086     return (Last);
1087 }
1088