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