xref: /freebsd/sys/contrib/dev/acpica/common/adwalk.c (revision 63d1fd5970ec814904aa0f4580b10a0d302d08b2)
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 <contrib/dev/acpica/include/acpi.h>
45 #include <contrib/dev/acpica/include/accommon.h>
46 #include <contrib/dev/acpica/include/acparser.h>
47 #include <contrib/dev/acpica/include/amlcode.h>
48 #include <contrib/dev/acpica/include/acdisasm.h>
49 #include <contrib/dev/acpica/include/acdispat.h>
50 #include <contrib/dev/acpica/include/acnamesp.h>
51 #include <contrib/dev/acpica/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         ACPI_FREE (WalkState);
331         return;
332     }
333 
334     Info.Flags = 0;
335     Info.Level = 0;
336     Info.WalkState = WalkState;
337 
338     AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmResourceDescendingOp,
339         AcpiDmCommonAscendingOp, &Info);
340     ACPI_FREE (WalkState);
341     return;
342 }
343 
344 
345 /*******************************************************************************
346  *
347  * FUNCTION:    AcpiDmDumpDescending
348  *
349  * PARAMETERS:  ASL_WALK_CALLBACK
350  *
351  * RETURN:      Status
352  *
353  * DESCRIPTION: Format and print contents of one parse Op.
354  *
355  ******************************************************************************/
356 
357 static ACPI_STATUS
358 AcpiDmDumpDescending (
359     ACPI_PARSE_OBJECT       *Op,
360     UINT32                  Level,
361     void                    *Context)
362 {
363     ACPI_OP_WALK_INFO       *Info = Context;
364     char                    *Path;
365 
366 
367     if (!Op)
368     {
369         return (AE_OK);
370     }
371 
372     /* Most of the information (count, level, name) here */
373 
374     Info->Count++;
375     AcpiOsPrintf ("% 5d [%2.2d] ", Info->Count, Level);
376     AcpiDmIndent (Level);
377     AcpiOsPrintf ("%-28s", AcpiPsGetOpcodeName (Op->Common.AmlOpcode));
378 
379     /* Extra info is helpful */
380 
381     switch (Op->Common.AmlOpcode)
382     {
383     case AML_BYTE_OP:
384 
385         AcpiOsPrintf ("%2.2X", (UINT32) Op->Common.Value.Integer);
386         break;
387 
388     case AML_WORD_OP:
389 
390         AcpiOsPrintf ("%4.4X", (UINT32) Op->Common.Value.Integer);
391         break;
392 
393     case AML_DWORD_OP:
394 
395         AcpiOsPrintf ("%8.8X", (UINT32) Op->Common.Value.Integer);
396         break;
397 
398     case AML_QWORD_OP:
399 
400         AcpiOsPrintf ("%8.8X%8.8X", ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
401         break;
402 
403     case AML_INT_NAMEPATH_OP:
404 
405         if (Op->Common.Value.String)
406         {
407             AcpiNsExternalizeName (ACPI_UINT32_MAX, Op->Common.Value.String,
408                 NULL, &Path);
409             AcpiOsPrintf ("%s %p", Path, Op->Common.Node);
410             ACPI_FREE (Path);
411         }
412         else
413         {
414             AcpiOsPrintf ("[NULL]");
415         }
416         break;
417 
418     case AML_NAME_OP:
419     case AML_METHOD_OP:
420     case AML_DEVICE_OP:
421     case AML_INT_NAMEDFIELD_OP:
422 
423         AcpiOsPrintf ("%4.4s", ACPI_CAST_PTR (char, &Op->Named.Name));
424         break;
425 
426     default:
427 
428         break;
429     }
430 
431     AcpiOsPrintf ("\n");
432     return (AE_OK);
433 }
434 
435 
436 /*******************************************************************************
437  *
438  * FUNCTION:    AcpiDmFindOrphanDescending
439  *
440  * PARAMETERS:  ASL_WALK_CALLBACK
441  *
442  * RETURN:      Status
443  *
444  * DESCRIPTION: Check namepath Ops for orphaned method invocations
445  *
446  * Note: Parts of this are experimental, under possible further development.
447  *
448  ******************************************************************************/
449 
450 static ACPI_STATUS
451 AcpiDmFindOrphanDescending (
452     ACPI_PARSE_OBJECT       *Op,
453     UINT32                  Level,
454     void                    *Context)
455 {
456     const ACPI_OPCODE_INFO  *OpInfo;
457     ACPI_PARSE_OBJECT       *ChildOp;
458     ACPI_PARSE_OBJECT       *NextOp;
459     ACPI_PARSE_OBJECT       *ParentOp;
460     UINT32                  ArgCount;
461 
462 
463     if (!Op)
464     {
465         return (AE_OK);
466     }
467 
468     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
469 
470     switch (Op->Common.AmlOpcode)
471     {
472 #ifdef ACPI_UNDER_DEVELOPMENT
473     case AML_ADD_OP:
474 
475         ChildOp = Op->Common.Value.Arg;
476         if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
477             !ChildOp->Common.Node)
478         {
479             AcpiNsExternalizeName (ACPI_UINT32_MAX, ChildOp->Common.Value.String,
480                 NULL, &Path);
481             AcpiOsPrintf ("/* %-16s A-NAMEPATH: %s  */\n",
482                 Op->Common.AmlOpName, Path);
483             ACPI_FREE (Path);
484 
485             NextOp = Op->Common.Next;
486             if (!NextOp)
487             {
488                 /* This NamePath has no args, assume it is an integer */
489 
490                 AcpiDmAddOpToExternalList (ChildOp,
491                     ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
492                 return (AE_OK);
493             }
494 
495             ArgCount = AcpiDmInspectPossibleArgs (3, 1, NextOp);
496             AcpiOsPrintf ("/* A-CHILDREN: %u Actual %u */\n",
497                 ArgCount, AcpiDmCountChildren (Op));
498 
499             if (ArgCount < 1)
500             {
501                 /* One Arg means this is just a Store(Name,Target) */
502 
503                 AcpiDmAddOpToExternalList (ChildOp,
504                     ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
505                 return (AE_OK);
506             }
507 
508             AcpiDmAddOpToExternalList (ChildOp,
509                 ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0);
510         }
511         break;
512 
513 #endif
514 
515     case AML_STORE_OP:
516 
517         ChildOp = Op->Common.Value.Arg;
518         if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
519             !ChildOp->Common.Node)
520         {
521             NextOp = Op->Common.Next;
522             if (!NextOp)
523             {
524                 /* This NamePath has no args, assume it is an integer */
525 
526                 AcpiDmAddOpToExternalList (ChildOp,
527                     ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
528                 return (AE_OK);
529             }
530 
531             ArgCount = AcpiDmInspectPossibleArgs (2, 1, NextOp);
532             if (ArgCount <= 1)
533             {
534                 /* One Arg means this is just a Store(Name,Target) */
535 
536                 AcpiDmAddOpToExternalList (ChildOp,
537                     ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, ArgCount, 0);
538                 return (AE_OK);
539             }
540 
541             AcpiDmAddOpToExternalList (ChildOp,
542                 ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0);
543         }
544         break;
545 
546     case AML_INT_NAMEPATH_OP:
547 
548         /* Must examine parent to see if this namepath is an argument */
549 
550         ParentOp = Op->Common.Parent;
551         OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode);
552 
553         if ((OpInfo->Class != AML_CLASS_EXECUTE) &&
554             (OpInfo->Class != AML_CLASS_CREATE) &&
555             (OpInfo->ObjectType != ACPI_TYPE_LOCAL_ALIAS) &&
556             (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) &&
557             !Op->Common.Node)
558         {
559             ArgCount = AcpiDmInspectPossibleArgs (0, 0, Op);
560 
561             /*
562              * Check if namepath is a predicate for if/while or lone parameter to
563              * a return.
564              */
565             if (ArgCount == 0)
566             {
567                 if (((ParentOp->Common.AmlOpcode == AML_IF_OP) ||
568                      (ParentOp->Common.AmlOpcode == AML_WHILE_OP) ||
569                      (ParentOp->Common.AmlOpcode == AML_RETURN_OP)) &&
570 
571                      /* And namepath is the first argument */
572                      (ParentOp->Common.Value.Arg == Op))
573                 {
574                     AcpiDmAddOpToExternalList (Op,
575                         Op->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
576                     break;
577                 }
578             }
579 
580             /*
581              * This is a standalone namestring (not a parameter to another
582              * operator) - it *must* be a method invocation, nothing else is
583              * grammatically possible.
584              */
585             AcpiDmAddOpToExternalList (Op,
586                 Op->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0);
587         }
588         break;
589 
590     default:
591 
592         break;
593     }
594 
595     return (AE_OK);
596 }
597 
598 
599 /*******************************************************************************
600  *
601  * FUNCTION:    AcpiDmLoadDescendingOp
602  *
603  * PARAMETERS:  ASL_WALK_CALLBACK
604  *
605  * RETURN:      Status
606  *
607  * DESCRIPTION: Descending handler for namespace control method object load
608  *
609  ******************************************************************************/
610 
611 static ACPI_STATUS
612 AcpiDmLoadDescendingOp (
613     ACPI_PARSE_OBJECT       *Op,
614     UINT32                  Level,
615     void                    *Context)
616 {
617     ACPI_OP_WALK_INFO       *Info = Context;
618     const ACPI_OPCODE_INFO  *OpInfo;
619     ACPI_WALK_STATE         *WalkState;
620     ACPI_OBJECT_TYPE        ObjectType;
621     ACPI_STATUS             Status;
622     char                    *Path = NULL;
623     ACPI_PARSE_OBJECT       *NextOp;
624     ACPI_NAMESPACE_NODE     *Node;
625     char                    FieldPath[5];
626     BOOLEAN                 PreDefined = FALSE;
627     UINT8                   PreDefineIndex = 0;
628 
629 
630     WalkState = Info->WalkState;
631     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
632     ObjectType = OpInfo->ObjectType;
633     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
634 
635     /* Only interested in operators that create new names */
636 
637     if (!(OpInfo->Flags & AML_NAMED) &&
638         !(OpInfo->Flags & AML_CREATE))
639     {
640         goto Exit;
641     }
642 
643     /* Get the NamePath from the appropriate place */
644 
645     if (OpInfo->Flags & AML_NAMED)
646     {
647         /* For all named operators, get the new name */
648 
649         Path = (char *) Op->Named.Path;
650 
651         if (!Path && Op->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP)
652         {
653             *ACPI_CAST_PTR (UINT32, &FieldPath[0]) = Op->Named.Name;
654             FieldPath[4] = 0;
655             Path = FieldPath;
656         }
657     }
658     else if (OpInfo->Flags & AML_CREATE)
659     {
660         /* New name is the last child */
661 
662         NextOp = Op->Common.Value.Arg;
663 
664         while (NextOp->Common.Next)
665         {
666             NextOp = NextOp->Common.Next;
667         }
668 
669         Path = NextOp->Common.Value.String;
670     }
671 
672     if (!Path)
673     {
674         goto Exit;
675     }
676 
677     /* Insert the name into the namespace */
678 
679     Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
680         ACPI_IMODE_LOAD_PASS2, ACPI_NS_DONT_OPEN_SCOPE,
681         WalkState, &Node);
682 
683     Op->Common.Node = Node;
684 
685     if (ACPI_SUCCESS (Status))
686     {
687         /* Check if it's a predefined node */
688 
689         while (AcpiGbl_PreDefinedNames[PreDefineIndex].Name)
690         {
691             if (ACPI_COMPARE_NAME (Node->Name.Ascii,
692                 AcpiGbl_PreDefinedNames[PreDefineIndex].Name))
693             {
694                 PreDefined = TRUE;
695                 break;
696             }
697 
698             PreDefineIndex++;
699         }
700 
701         /*
702          * Set node owner id if it satisfies all the following conditions:
703          * 1) Not a predefined node, _SB_ etc
704          * 2) Not the root node
705          * 3) Not a node created by Scope
706          */
707 
708         if (!PreDefined && Node != AcpiGbl_RootNode &&
709             Op->Common.AmlOpcode != AML_SCOPE_OP)
710         {
711             Node->OwnerId = WalkState->OwnerId;
712         }
713     }
714 
715 
716 Exit:
717 
718     if (AcpiNsOpensScope (ObjectType))
719     {
720         if (Op->Common.Node)
721         {
722             Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType,
723                 WalkState);
724             if (ACPI_FAILURE (Status))
725             {
726                 return (Status);
727             }
728         }
729     }
730 
731     return (AE_OK);
732 }
733 
734 
735 /*******************************************************************************
736  *
737  * FUNCTION:    AcpiDmXrefDescendingOp
738  *
739  * PARAMETERS:  ASL_WALK_CALLBACK
740  *
741  * RETURN:      Status
742  *
743  * DESCRIPTION: Descending handler for namespace cross reference
744  *
745  ******************************************************************************/
746 
747 static ACPI_STATUS
748 AcpiDmXrefDescendingOp (
749     ACPI_PARSE_OBJECT       *Op,
750     UINT32                  Level,
751     void                    *Context)
752 {
753     ACPI_OP_WALK_INFO       *Info = Context;
754     const ACPI_OPCODE_INFO  *OpInfo;
755     ACPI_WALK_STATE         *WalkState;
756     ACPI_OBJECT_TYPE        ObjectType;
757     ACPI_OBJECT_TYPE        ObjectType2;
758     ACPI_STATUS             Status;
759     char                    *Path = NULL;
760     ACPI_PARSE_OBJECT       *NextOp;
761     ACPI_NAMESPACE_NODE     *Node;
762     ACPI_OPERAND_OBJECT     *Object;
763     UINT32                  ParamCount = 0;
764     char                    *Pathname;
765     UINT16                  Flags = 0;
766 
767 
768     WalkState = Info->WalkState;
769     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
770     ObjectType = OpInfo->ObjectType;
771     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
772 
773     if ((!(OpInfo->Flags & AML_NAMED)) &&
774         (!(OpInfo->Flags & AML_CREATE)) &&
775         (Op->Common.AmlOpcode != AML_INT_NAMEPATH_OP) &&
776         (Op->Common.AmlOpcode != AML_NOTIFY_OP))
777     {
778         goto Exit;
779     }
780     else if (Op->Common.Parent &&
781              Op->Common.Parent->Common.AmlOpcode == AML_EXTERNAL_OP)
782     {
783         /* External() NamePath */
784 
785         Path = Op->Common.Value.String;
786         ObjectType = (ACPI_OBJECT_TYPE) Op->Common.Next->Common.Value.Integer;
787         if (ObjectType == ACPI_TYPE_METHOD)
788         {
789             ParamCount = (UINT32)
790                 Op->Common.Next->Common.Next->Common.Value.Integer;
791         }
792 
793         Flags |= ACPI_EXT_RESOLVED_REFERENCE | ACPI_EXT_ORIGIN_FROM_OPCODE;
794         AcpiDmAddOpToExternalList (Op, Path,
795             (UINT8) ObjectType, ParamCount, Flags);
796 
797         goto Exit;
798     }
799 
800     /* Get the NamePath from the appropriate place */
801 
802     if (OpInfo->Flags & AML_NAMED)
803     {
804         /*
805          * Only these two operators (Alias, Scope) refer to an existing
806          * name, it is the first argument
807          */
808         if (Op->Common.AmlOpcode == AML_ALIAS_OP)
809         {
810             ObjectType = ACPI_TYPE_ANY;
811 
812             NextOp = Op->Common.Value.Arg;
813             NextOp = NextOp->Common.Value.Arg;
814             if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
815             {
816                 Path = NextOp->Common.Value.String;
817             }
818         }
819         else if (Op->Common.AmlOpcode == AML_SCOPE_OP)
820         {
821             Path = (char *) Op->Named.Path;
822         }
823     }
824     else if (OpInfo->Flags & AML_CREATE)
825     {
826         /* Referenced Buffer Name is the first child */
827 
828         ObjectType = ACPI_TYPE_BUFFER; /* Change from TYPE_BUFFER_FIELD */
829 
830         NextOp = Op->Common.Value.Arg;
831         if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
832         {
833             Path = NextOp->Common.Value.String;
834         }
835     }
836     else if (Op->Common.AmlOpcode == AML_NOTIFY_OP)
837     {
838         Path = Op->Common.Value.Arg->Asl.Value.String;
839     }
840     else
841     {
842         Path = Op->Common.Value.String;
843     }
844 
845     if (!Path)
846     {
847         goto Exit;
848     }
849 
850     /*
851      * Lookup the name in the namespace. Name must exist at this point, or it
852      * is an invalid reference.
853      *
854      * The namespace is also used as a lookup table for references to resource
855      * descriptors and the fields within them.
856      */
857     Node = NULL;
858     Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY,
859         ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
860         WalkState, &Node);
861 
862     if (ACPI_SUCCESS (Status) && (Node->Flags & ANOBJ_IS_EXTERNAL))
863     {
864         /* Node was created by an External() statement */
865 
866         Status = AE_NOT_FOUND;
867     }
868 
869     if (ACPI_FAILURE (Status))
870     {
871         if (Status == AE_NOT_FOUND)
872         {
873             /*
874              * Add this symbol as an external declaration, except if the
875              * parent is a CondRefOf operator. For this operator, we do not
876              * need an external, nor do we want one, since this can cause
877              * disassembly problems if the symbol is actually a control
878              * method.
879              */
880             if (!(Op->Asl.Parent &&
881                 (Op->Asl.Parent->Asl.AmlOpcode == AML_COND_REF_OF_OP)))
882             {
883                 if (Node)
884                 {
885                     AcpiDmAddNodeToExternalList (Node,
886                         (UINT8) ObjectType, 7, Flags);
887                 }
888                 else
889                 {
890                     AcpiDmAddOpToExternalList (Op, Path,
891                         (UINT8) ObjectType, 7, Flags);
892                 }
893             }
894         }
895     }
896 
897     /*
898      * Found the node, but check if it came from an external table.
899      * Add it to external list. Note: Node->OwnerId == 0 indicates
900      * one of the built-in ACPI Names (_OS_ etc.) which can safely
901      * be ignored.
902      */
903     else if (Node->OwnerId &&
904             (WalkState->OwnerId != Node->OwnerId))
905     {
906         ObjectType2 = ObjectType;
907 
908         Object = AcpiNsGetAttachedObject (Node);
909         if (Object)
910         {
911             ObjectType2 = Object->Common.Type;
912             if (ObjectType2 == ACPI_TYPE_METHOD)
913             {
914                 ParamCount = Object->Method.ParamCount;
915             }
916         }
917 
918         Pathname = AcpiNsGetExternalPathname (Node);
919         if (!Pathname)
920         {
921             return (AE_NO_MEMORY);
922         }
923 
924         AcpiDmAddNodeToExternalList (Node, (UINT8) ObjectType2,
925             ParamCount, ACPI_EXT_RESOLVED_REFERENCE);
926 
927         ACPI_FREE (Pathname);
928         Op->Common.Node = Node;
929     }
930     else
931     {
932         Op->Common.Node = Node;
933     }
934 
935 
936 Exit:
937     /* Open new scope if necessary */
938 
939     if (AcpiNsOpensScope (ObjectType))
940     {
941         if (Op->Common.Node)
942         {
943             Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType,
944                 WalkState);
945             if (ACPI_FAILURE (Status))
946             {
947                 return (Status);
948             }
949         }
950     }
951 
952     return (AE_OK);
953 }
954 
955 
956 /*******************************************************************************
957  *
958  * FUNCTION:    AcpiDmResourceDescendingOp
959  *
960  * PARAMETERS:  ASL_WALK_CALLBACK
961  *
962  * RETURN:      None
963  *
964  * DESCRIPTION: Process one parse op during symbolic resource index conversion.
965  *
966  ******************************************************************************/
967 
968 static ACPI_STATUS
969 AcpiDmResourceDescendingOp (
970     ACPI_PARSE_OBJECT       *Op,
971     UINT32                  Level,
972     void                    *Context)
973 {
974     ACPI_OP_WALK_INFO       *Info = Context;
975     const ACPI_OPCODE_INFO  *OpInfo;
976     ACPI_WALK_STATE         *WalkState;
977     ACPI_OBJECT_TYPE        ObjectType;
978     ACPI_STATUS             Status;
979 
980 
981     WalkState = Info->WalkState;
982     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
983 
984     /* Open new scope if necessary */
985 
986     ObjectType = OpInfo->ObjectType;
987     if (AcpiNsOpensScope (ObjectType))
988     {
989         if (Op->Common.Node)
990         {
991 
992             Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType,
993                 WalkState);
994             if (ACPI_FAILURE (Status))
995             {
996                 return (Status);
997             }
998         }
999     }
1000 
1001     /*
1002      * Check if this operator contains a reference to a resource descriptor.
1003      * If so, convert the reference into a symbolic reference.
1004      */
1005     AcpiDmCheckResourceReference (Op, WalkState);
1006     return (AE_OK);
1007 }
1008 
1009 
1010 /*******************************************************************************
1011  *
1012  * FUNCTION:    AcpiDmCommonAscendingOp
1013  *
1014  * PARAMETERS:  ASL_WALK_CALLBACK
1015  *
1016  * RETURN:      None
1017  *
1018  * DESCRIPTION: Ascending handler for combined parse/namespace walks. Closes
1019  *              scope if necessary.
1020  *
1021  ******************************************************************************/
1022 
1023 static ACPI_STATUS
1024 AcpiDmCommonAscendingOp (
1025     ACPI_PARSE_OBJECT       *Op,
1026     UINT32                  Level,
1027     void                    *Context)
1028 {
1029     ACPI_OP_WALK_INFO       *Info = Context;
1030     const ACPI_OPCODE_INFO  *OpInfo;
1031     ACPI_OBJECT_TYPE        ObjectType;
1032 
1033 
1034     /* Close scope if necessary */
1035 
1036     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
1037     ObjectType = OpInfo->ObjectType;
1038     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
1039 
1040     if (AcpiNsOpensScope (ObjectType))
1041     {
1042         (void) AcpiDsScopeStackPop (Info->WalkState);
1043     }
1044 
1045     return (AE_OK);
1046 }
1047 
1048 
1049 /*******************************************************************************
1050  *
1051  * FUNCTION:    AcpiDmInspectPossibleArgs
1052  *
1053  * PARAMETERS:  CurrentOpArgCount   - Which arg of the current op was the
1054  *                                    possible method invocation found
1055  *              TargetCount         - Number of targets (0,1,2) for this op
1056  *              Op                  - Parse op
1057  *
1058  * RETURN:      Status
1059  *
1060  * DESCRIPTION: Examine following args and next ops for possible arguments
1061  *              for an unrecognized method invocation.
1062  *
1063  ******************************************************************************/
1064 
1065 static UINT32
1066 AcpiDmInspectPossibleArgs (
1067     UINT32                  CurrentOpArgCount,
1068     UINT32                  TargetCount,
1069     ACPI_PARSE_OBJECT       *Op)
1070 {
1071     const ACPI_OPCODE_INFO  *OpInfo;
1072     UINT32                  i;
1073     UINT32                  ArgumentCount = 0;
1074     ACPI_PARSE_OBJECT       *NextOp;
1075     ACPI_PARSE_OBJECT       *ExecuteOp;
1076 
1077 
1078     if (!Op)
1079     {
1080         return (0);
1081     }
1082 
1083     /* Lookahead for the maximum number of possible arguments */
1084 
1085     NextOp = Op->Common.Next;
1086 
1087     for (i = 0; (i < ACPI_METHOD_NUM_ARGS) && NextOp; i++)
1088     {
1089         OpInfo = AcpiPsGetOpcodeInfo (NextOp->Common.AmlOpcode);
1090 
1091         /* Any one of these operators is "very probably" not a method arg */
1092 
1093         if ((NextOp->Common.AmlOpcode == AML_STORE_OP) ||
1094             (NextOp->Common.AmlOpcode == AML_NOTIFY_OP) ||
1095             (OpInfo->Class == AML_CLASS_CONTROL) ||
1096             (OpInfo->Class == AML_CLASS_CREATE) ||
1097             (OpInfo->Class == AML_CLASS_NAMED_OBJECT))
1098         {
1099             break;
1100         }
1101 
1102         if (OpInfo->Class == AML_CLASS_EXECUTE)
1103         {
1104             /* Probable that this is method arg if there is no target */
1105 
1106             ExecuteOp = NextOp->Common.Value.Arg;
1107             while (ExecuteOp)
1108             {
1109                 if ((ExecuteOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
1110                     (ExecuteOp->Common.Value.Arg == NULL))
1111                 {
1112                     /* No target, could be a method arg */
1113 
1114                     break;
1115                 }
1116 
1117                 if (NextOp->Common.AmlOpcode == AML_REF_OF_OP)
1118                 {
1119                     break;
1120                 }
1121 
1122                 ExecuteOp = ExecuteOp->Common.Next;
1123             }
1124 
1125             if (!ExecuteOp)
1126             {
1127                 /* Has a target, not method arg */
1128 
1129                 return (ArgumentCount);
1130             }
1131         }
1132 
1133         ArgumentCount++;
1134         NextOp = NextOp->Common.Next;
1135     }
1136 
1137     return (ArgumentCount);
1138 }
1139