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