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     UINT16                  Flags = 0;
764 
765 
766     WalkState = Info->WalkState;
767     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
768     ObjectType = OpInfo->ObjectType;
769     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
770 
771     if ((!(OpInfo->Flags & AML_NAMED)) &&
772         (!(OpInfo->Flags & AML_CREATE)) &&
773         (Op->Common.AmlOpcode != AML_INT_NAMEPATH_OP) &&
774         (Op->Common.AmlOpcode != AML_NOTIFY_OP))
775     {
776         goto Exit;
777     }
778     else if (Op->Common.Parent &&
779              Op->Common.Parent->Common.AmlOpcode == AML_EXTERNAL_OP)
780     {
781         /* External() NamePath */
782 
783         Path = Op->Common.Value.String;
784         ObjectType = (ACPI_OBJECT_TYPE) Op->Common.Next->Common.Value.Integer;
785         if (ObjectType == ACPI_TYPE_METHOD)
786         {
787             ParamCount = (UINT32)
788                 Op->Common.Next->Common.Next->Common.Value.Integer;
789         }
790 
791         AcpiDmAddOpToExternalList (Op, Path,
792             (UINT8) ObjectType, ParamCount, Flags);
793 
794         goto Exit;
795     }
796 
797     /* Get the NamePath from the appropriate place */
798 
799     if (OpInfo->Flags & AML_NAMED)
800     {
801         /*
802          * Only these two operators (Alias, Scope) refer to an existing
803          * name, it is the first argument
804          */
805         if (Op->Common.AmlOpcode == AML_ALIAS_OP)
806         {
807             ObjectType = ACPI_TYPE_ANY;
808 
809             NextOp = Op->Common.Value.Arg;
810             NextOp = NextOp->Common.Value.Arg;
811             if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
812             {
813                 Path = NextOp->Common.Value.String;
814             }
815         }
816         else if (Op->Common.AmlOpcode == AML_SCOPE_OP)
817         {
818             Path = (char *) Op->Named.Path;
819         }
820     }
821     else if (OpInfo->Flags & AML_CREATE)
822     {
823         /* Referenced Buffer Name is the first child */
824 
825         ObjectType = ACPI_TYPE_BUFFER; /* Change from TYPE_BUFFER_FIELD */
826 
827         NextOp = Op->Common.Value.Arg;
828         if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
829         {
830             Path = NextOp->Common.Value.String;
831         }
832     }
833     else if (Op->Common.AmlOpcode == AML_NOTIFY_OP)
834     {
835         Path = Op->Common.Value.Arg->Asl.Value.String;
836     }
837     else
838     {
839         Path = Op->Common.Value.String;
840     }
841 
842     if (!Path)
843     {
844         goto Exit;
845     }
846 
847     /*
848      * Lookup the name in the namespace. Name must exist at this point, or it
849      * is an invalid reference.
850      *
851      * The namespace is also used as a lookup table for references to resource
852      * descriptors and the fields within them.
853      */
854     Node = NULL;
855     Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY,
856         ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
857         WalkState, &Node);
858     if (ACPI_SUCCESS (Status) && (Node->Flags & ANOBJ_IS_EXTERNAL))
859     {
860         /* Node was created by an External() statement */
861 
862         Status = AE_NOT_FOUND;
863         Flags = ACPI_EXT_RESOLVED_REFERENCE;
864     }
865 
866     if (ACPI_FAILURE (Status))
867     {
868         if (Status == AE_NOT_FOUND)
869         {
870             /*
871              * Add this symbol as an external declaration, except if the
872              * parent is a CondRefOf operator. For this operator, we do not
873              * need an external, nor do we want one, since this can cause
874              * disassembly problems if the symbol is actually a control
875              * method.
876              */
877             if (!(Op->Asl.Parent &&
878                 (Op->Asl.Parent->Asl.AmlOpcode == AML_COND_REF_OF_OP)))
879             {
880                 if (Node)
881                 {
882                     AcpiDmAddNodeToExternalList (Node,
883                         (UINT8) ObjectType, 0, Flags);
884                 }
885                 else
886                 {
887                     AcpiDmAddOpToExternalList (Op, Path,
888                         (UINT8) ObjectType, 0, Flags);
889                 }
890             }
891         }
892     }
893 
894     /*
895      * Found the node, but check if it came from an external table.
896      * Add it to external list. Note: Node->OwnerId == 0 indicates
897      * one of the built-in ACPI Names (_OS_ etc.) which can safely
898      * be ignored.
899      */
900     else if (Node->OwnerId &&
901             (WalkState->OwnerId != Node->OwnerId))
902     {
903         ObjectType2 = ObjectType;
904 
905         Object = AcpiNsGetAttachedObject (Node);
906         if (Object)
907         {
908             ObjectType2 = Object->Common.Type;
909             if (ObjectType2 == ACPI_TYPE_METHOD)
910             {
911                 ParamCount = Object->Method.ParamCount;
912             }
913         }
914 
915         Pathname = AcpiNsGetExternalPathname (Node);
916         if (!Pathname)
917         {
918             return (AE_NO_MEMORY);
919         }
920 
921         AcpiDmAddNodeToExternalList (Node, (UINT8) ObjectType2,
922             ParamCount, ACPI_EXT_RESOLVED_REFERENCE);
923 
924         ACPI_FREE (Pathname);
925         Op->Common.Node = Node;
926     }
927     else
928     {
929         Op->Common.Node = Node;
930     }
931 
932 
933 Exit:
934     /* Open new scope if necessary */
935 
936     if (AcpiNsOpensScope (ObjectType))
937     {
938         if (Op->Common.Node)
939         {
940             Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType,
941                 WalkState);
942             if (ACPI_FAILURE (Status))
943             {
944                 return (Status);
945             }
946         }
947     }
948 
949     return (AE_OK);
950 }
951 
952 
953 /*******************************************************************************
954  *
955  * FUNCTION:    AcpiDmResourceDescendingOp
956  *
957  * PARAMETERS:  ASL_WALK_CALLBACK
958  *
959  * RETURN:      None
960  *
961  * DESCRIPTION: Process one parse op during symbolic resource index conversion.
962  *
963  ******************************************************************************/
964 
965 static ACPI_STATUS
966 AcpiDmResourceDescendingOp (
967     ACPI_PARSE_OBJECT       *Op,
968     UINT32                  Level,
969     void                    *Context)
970 {
971     ACPI_OP_WALK_INFO       *Info = Context;
972     const ACPI_OPCODE_INFO  *OpInfo;
973     ACPI_WALK_STATE         *WalkState;
974     ACPI_OBJECT_TYPE        ObjectType;
975     ACPI_STATUS             Status;
976 
977 
978     WalkState = Info->WalkState;
979     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
980 
981     /* Open new scope if necessary */
982 
983     ObjectType = OpInfo->ObjectType;
984     if (AcpiNsOpensScope (ObjectType))
985     {
986         if (Op->Common.Node)
987         {
988 
989             Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType,
990                 WalkState);
991             if (ACPI_FAILURE (Status))
992             {
993                 return (Status);
994             }
995         }
996     }
997 
998     /*
999      * Check if this operator contains a reference to a resource descriptor.
1000      * If so, convert the reference into a symbolic reference.
1001      */
1002     AcpiDmCheckResourceReference (Op, WalkState);
1003     return (AE_OK);
1004 }
1005 
1006 
1007 /*******************************************************************************
1008  *
1009  * FUNCTION:    AcpiDmCommonAscendingOp
1010  *
1011  * PARAMETERS:  ASL_WALK_CALLBACK
1012  *
1013  * RETURN:      None
1014  *
1015  * DESCRIPTION: Ascending handler for combined parse/namespace walks. Closes
1016  *              scope if necessary.
1017  *
1018  ******************************************************************************/
1019 
1020 static ACPI_STATUS
1021 AcpiDmCommonAscendingOp (
1022     ACPI_PARSE_OBJECT       *Op,
1023     UINT32                  Level,
1024     void                    *Context)
1025 {
1026     ACPI_OP_WALK_INFO       *Info = Context;
1027     const ACPI_OPCODE_INFO  *OpInfo;
1028     ACPI_OBJECT_TYPE        ObjectType;
1029 
1030 
1031     /* Close scope if necessary */
1032 
1033     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
1034     ObjectType = OpInfo->ObjectType;
1035     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
1036 
1037     if (AcpiNsOpensScope (ObjectType))
1038     {
1039         (void) AcpiDsScopeStackPop (Info->WalkState);
1040     }
1041 
1042     return (AE_OK);
1043 }
1044 
1045 
1046 /*******************************************************************************
1047  *
1048  * FUNCTION:    AcpiDmInspectPossibleArgs
1049  *
1050  * PARAMETERS:  CurrentOpArgCount   - Which arg of the current op was the
1051  *                                    possible method invocation found
1052  *              TargetCount         - Number of targets (0,1,2) for this op
1053  *              Op                  - Parse op
1054  *
1055  * RETURN:      Status
1056  *
1057  * DESCRIPTION: Examine following args and next ops for possible arguments
1058  *              for an unrecognized method invocation.
1059  *
1060  ******************************************************************************/
1061 
1062 static UINT32
1063 AcpiDmInspectPossibleArgs (
1064     UINT32                  CurrentOpArgCount,
1065     UINT32                  TargetCount,
1066     ACPI_PARSE_OBJECT       *Op)
1067 {
1068     const ACPI_OPCODE_INFO  *OpInfo;
1069     UINT32                  i;
1070     UINT32                  Last = 0;
1071     UINT32                  Lookahead;
1072 
1073 
1074     Lookahead = (ACPI_METHOD_NUM_ARGS + TargetCount) - CurrentOpArgCount;
1075 
1076     /* Lookahead for the maximum number of possible arguments */
1077 
1078     for (i = 0; i < Lookahead; i++)
1079     {
1080         if (!Op)
1081         {
1082             break;
1083         }
1084 
1085         OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
1086 
1087         /*
1088          * Any one of these operators is "very probably" not a method arg
1089          */
1090         if ((Op->Common.AmlOpcode == AML_STORE_OP) ||
1091             (Op->Common.AmlOpcode == AML_NOTIFY_OP))
1092         {
1093             break;
1094         }
1095 
1096         if ((OpInfo->Class != AML_CLASS_EXECUTE) &&
1097             (OpInfo->Class != AML_CLASS_CONTROL))
1098         {
1099             Last = i+1;
1100         }
1101 
1102         Op = Op->Common.Next;
1103     }
1104 
1105     return (Last);
1106 }
1107