]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/contrib/dev/acpica/common/adwalk.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / contrib / dev / acpica / common / adwalk.c
1 /******************************************************************************
2  *
3  * Module Name: adwalk - Application-level disassembler parse tree walk routines
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2011, 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 <contrib/dev/acpica/include/acpi.h>
46 #include <contrib/dev/acpica/include/accommon.h>
47 #include <contrib/dev/acpica/include/acparser.h>
48 #include <contrib/dev/acpica/include/amlcode.h>
49 #include <contrib/dev/acpica/include/acdisasm.h>
50 #include <contrib/dev/acpica/include/acdispat.h>
51 #include <contrib/dev/acpica/include/acnamesp.h>
52 #include <contrib/dev/acpica/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     case AML_WORD_OP:
377     case AML_DWORD_OP:
378         AcpiOsPrintf ("%X", (UINT32) Op->Common.Value.Integer);
379         break;
380
381     case AML_INT_NAMEPATH_OP:
382         if (Op->Common.Value.String)
383         {
384             AcpiNsExternalizeName (ACPI_UINT32_MAX, Op->Common.Value.String,
385                             NULL, &Path);
386             AcpiOsPrintf ("%s %p", Path, Op->Common.Node);
387             ACPI_FREE (Path);
388         }
389         else
390         {
391             AcpiOsPrintf ("[NULL]");
392         }
393         break;
394
395     case AML_NAME_OP:
396     case AML_METHOD_OP:
397     case AML_DEVICE_OP:
398     case AML_INT_NAMEDFIELD_OP:
399         AcpiOsPrintf ("%4.4s", ACPI_CAST_PTR (char, &Op->Named.Name));
400         break;
401
402     default:
403         break;
404     }
405
406     AcpiOsPrintf ("\n");
407     return (AE_OK);
408 }
409
410
411 /*******************************************************************************
412  *
413  * FUNCTION:    AcpiDmFindOrphanDescending
414  *
415  * PARAMETERS:  ASL_WALK_CALLBACK
416  *
417  * RETURN:      Status
418  *
419  * DESCRIPTION: Check namepath Ops for orphaned method invocations
420  *
421  * Note: Experimental.
422  *
423  ******************************************************************************/
424
425 static ACPI_STATUS
426 AcpiDmFindOrphanDescending (
427     ACPI_PARSE_OBJECT       *Op,
428     UINT32                  Level,
429     void                    *Context)
430 {
431     const ACPI_OPCODE_INFO  *OpInfo;
432     ACPI_PARSE_OBJECT       *ChildOp;
433     ACPI_PARSE_OBJECT       *NextOp;
434     ACPI_PARSE_OBJECT       *ParentOp;
435     UINT32                  ArgCount;
436
437
438     if (!Op)
439     {
440         return (AE_OK);
441     }
442
443     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
444
445     switch (Op->Common.AmlOpcode)
446     {
447 #ifdef ACPI_UNDER_DEVELOPMENT
448     case AML_ADD_OP:
449         ChildOp = Op->Common.Value.Arg;
450         if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
451             !ChildOp->Common.Node)
452         {
453             AcpiNsExternalizeName (ACPI_UINT32_MAX, ChildOp->Common.Value.String,
454                             NULL, &Path);
455             AcpiOsPrintf ("/* %-16s A-NAMEPATH: %s  */\n", Op->Common.AmlOpName, Path);
456             ACPI_FREE (Path);
457
458             NextOp = Op->Common.Next;
459             if (!NextOp)
460             {
461                 /* This NamePath has no args, assume it is an integer */
462
463                 AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0);
464                 return (AE_OK);
465             }
466
467             ArgCount = AcpiDmInspectPossibleArgs (3, 1, NextOp);
468             AcpiOsPrintf ("/* A-CHILDREN: %u Actual %u */\n", ArgCount, AcpiDmCountChildren (Op));
469
470             if (ArgCount < 1)
471             {
472                 /* One Arg means this is just a Store(Name,Target) */
473
474                 AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0);
475                 return (AE_OK);
476             }
477
478             AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount);
479         }
480         break;
481 #endif
482
483     case AML_STORE_OP:
484
485         ChildOp = Op->Common.Value.Arg;
486         if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
487             !ChildOp->Common.Node)
488         {
489             NextOp = Op->Common.Next;
490             if (!NextOp)
491             {
492                 /* This NamePath has no args, assume it is an integer */
493
494                 AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0);
495                 return (AE_OK);
496             }
497
498             ArgCount = AcpiDmInspectPossibleArgs (2, 1, NextOp);
499             if (ArgCount <= 1)
500             {
501                 /* One Arg means this is just a Store(Name,Target) */
502
503                 AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0);
504                 return (AE_OK);
505             }
506
507             AcpiDmAddToExternalList (ChildOp, ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount);
508         }
509         break;
510
511     case AML_INT_NAMEPATH_OP:
512
513         /* Must examine parent to see if this namepath is an argument */
514
515         ParentOp = Op->Common.Parent;
516         OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode);
517
518         if ((OpInfo->Class != AML_CLASS_EXECUTE) &&
519             (OpInfo->Class != AML_CLASS_CREATE) &&
520             (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) &&
521             !Op->Common.Node)
522         {
523             ArgCount = AcpiDmInspectPossibleArgs (0, 0, Op->Common.Next);
524
525             /*
526              * Check if namepath is a predicate for if/while or lone parameter to
527              * a return.
528              */
529             if (ArgCount == 0)
530             {
531                 if (((ParentOp->Common.AmlOpcode == AML_IF_OP) ||
532                      (ParentOp->Common.AmlOpcode == AML_WHILE_OP) ||
533                      (ParentOp->Common.AmlOpcode == AML_RETURN_OP)) &&
534
535                      /* And namepath is the first argument */
536                      (ParentOp->Common.Value.Arg == Op))
537                 {
538                     AcpiDmAddToExternalList (Op, Op->Common.Value.String, ACPI_TYPE_INTEGER, 0);
539                     break;
540                 }
541             }
542
543             /*
544              * This is a standalone namestring (not a parameter to another
545              * operator) - it *must* be a method invocation, nothing else is
546              * grammatically possible.
547              */
548             AcpiDmAddToExternalList (Op, Op->Common.Value.String, ACPI_TYPE_METHOD, ArgCount);
549
550         }
551         break;
552
553     default:
554         break;
555     }
556
557     return (AE_OK);
558 }
559
560
561 /*******************************************************************************
562  *
563  * FUNCTION:    AcpiDmLoadDescendingOp
564  *
565  * PARAMETERS:  ASL_WALK_CALLBACK
566  *
567  * RETURN:      Status
568  *
569  * DESCRIPTION: Descending handler for namespace control method object load
570  *
571  ******************************************************************************/
572
573 static ACPI_STATUS
574 AcpiDmLoadDescendingOp (
575     ACPI_PARSE_OBJECT       *Op,
576     UINT32                  Level,
577     void                    *Context)
578 {
579     ACPI_OP_WALK_INFO       *Info = Context;
580     const ACPI_OPCODE_INFO  *OpInfo;
581     ACPI_WALK_STATE         *WalkState;
582     ACPI_OBJECT_TYPE        ObjectType;
583     ACPI_STATUS             Status;
584     char                    *Path = NULL;
585     ACPI_PARSE_OBJECT       *NextOp;
586     ACPI_NAMESPACE_NODE     *Node;
587     char                    FieldPath[5];
588     BOOLEAN                 PreDefined = FALSE;
589     UINT8                   PreDefineIndex = 0;
590
591
592     WalkState = Info->WalkState;
593     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
594     ObjectType = OpInfo->ObjectType;
595     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
596
597     /* Only interested in operators that create new names */
598
599     if (!(OpInfo->Flags & AML_NAMED) &&
600         !(OpInfo->Flags & AML_CREATE))
601     {
602         goto Exit;
603     }
604
605     /* Get the NamePath from the appropriate place */
606
607     if (OpInfo->Flags & AML_NAMED)
608     {
609         /* For all named operators, get the new name */
610
611         Path = (char *) Op->Named.Path;
612
613         if (!Path && Op->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP)
614         {
615             *ACPI_CAST_PTR (UINT32, &FieldPath[0]) = Op->Named.Name;
616             FieldPath[4] = 0;
617             Path = FieldPath;
618         }
619     }
620     else if (OpInfo->Flags & AML_CREATE)
621     {
622         /* New name is the last child */
623
624         NextOp = Op->Common.Value.Arg;
625
626         while (NextOp->Common.Next)
627         {
628             NextOp = NextOp->Common.Next;
629         }
630         Path = NextOp->Common.Value.String;
631     }
632
633     if (!Path)
634     {
635         goto Exit;
636     }
637
638     /* Insert the name into the namespace */
639
640     Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
641                 ACPI_IMODE_LOAD_PASS2, ACPI_NS_DONT_OPEN_SCOPE,
642                 WalkState, &Node);
643
644     Op->Common.Node = Node;
645
646     if (ACPI_SUCCESS (Status))
647     {
648         /* Check if it's a predefined node */
649
650         while (AcpiGbl_PreDefinedNames[PreDefineIndex].Name)
651         {
652             if (!ACPI_STRNCMP (Node->Name.Ascii,
653                 AcpiGbl_PreDefinedNames[PreDefineIndex].Name, 4))
654             {
655                 PreDefined = TRUE;
656                 break;
657             }
658
659             PreDefineIndex++;
660         }
661
662         /*
663          * Set node owner id if it satisfies all the following conditions:
664          * 1) Not a predefined node, _SB_ etc
665          * 2) Not the root node
666          * 3) Not a node created by Scope
667          */
668
669         if (!PreDefined && Node != AcpiGbl_RootNode &&
670             Op->Common.AmlOpcode != AML_SCOPE_OP)
671         {
672             Node->OwnerId = WalkState->OwnerId;
673         }
674     }
675
676
677 Exit:
678
679     if (AcpiNsOpensScope (ObjectType))
680     {
681         if (Op->Common.Node)
682         {
683             Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState);
684             if (ACPI_FAILURE (Status))
685             {
686                 return (Status);
687             }
688         }
689     }
690
691     return (AE_OK);
692 }
693
694
695 /*******************************************************************************
696  *
697  * FUNCTION:    AcpiDmXrefDescendingOp
698  *
699  * PARAMETERS:  ASL_WALK_CALLBACK
700  *
701  * RETURN:      Status
702  *
703  * DESCRIPTION: Descending handler for namespace cross reference
704  *
705  ******************************************************************************/
706
707 static ACPI_STATUS
708 AcpiDmXrefDescendingOp (
709     ACPI_PARSE_OBJECT       *Op,
710     UINT32                  Level,
711     void                    *Context)
712 {
713     ACPI_OP_WALK_INFO       *Info = Context;
714     const ACPI_OPCODE_INFO  *OpInfo;
715     ACPI_WALK_STATE         *WalkState;
716     ACPI_OBJECT_TYPE        ObjectType;
717     ACPI_OBJECT_TYPE        ObjectType2;
718     ACPI_STATUS             Status;
719     char                    *Path = NULL;
720     ACPI_PARSE_OBJECT       *NextOp;
721     ACPI_NAMESPACE_NODE     *Node;
722     ACPI_OPERAND_OBJECT     *Object;
723     UINT32                  ParamCount = 0;
724
725
726     WalkState = Info->WalkState;
727     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
728     ObjectType = OpInfo->ObjectType;
729     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
730
731     if ((!(OpInfo->Flags & AML_NAMED)) &&
732         (!(OpInfo->Flags & AML_CREATE)) &&
733         (Op->Common.AmlOpcode != AML_INT_NAMEPATH_OP))
734     {
735         goto Exit;
736     }
737
738     /* Get the NamePath from the appropriate place */
739
740     if (OpInfo->Flags & AML_NAMED)
741     {
742         if ((Op->Common.AmlOpcode == AML_ALIAS_OP) ||
743             (Op->Common.AmlOpcode == AML_SCOPE_OP))
744         {
745             /*
746              * Only these two operators refer to an existing name,
747              * first argument
748              */
749             Path = (char *) Op->Named.Path;
750         }
751     }
752     else if (OpInfo->Flags & AML_CREATE)
753     {
754         /* Referenced Buffer Name is the first child */
755
756         NextOp = Op->Common.Value.Arg;
757         if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
758         {
759             Path = NextOp->Common.Value.String;
760         }
761     }
762     else
763     {
764         Path = Op->Common.Value.String;
765     }
766
767     if (!Path)
768     {
769         goto Exit;
770     }
771
772     /*
773      * Lookup the name in the namespace.  Name must exist at this point, or it
774      * is an invalid reference.
775      *
776      * The namespace is also used as a lookup table for references to resource
777      * descriptors and the fields within them.
778      */
779     Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY,
780                 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
781                 WalkState, &Node);
782     if (ACPI_FAILURE (Status))
783     {
784         if (Status == AE_NOT_FOUND)
785         {
786             AcpiDmAddToExternalList (Op, Path, (UINT8) ObjectType, 0);
787
788             /*
789              * We could install this into the namespace, but we catch duplicate
790              * externals when they are added to the list.
791              */
792 #if 0
793             Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY,
794                        ACPI_IMODE_LOAD_PASS1, ACPI_NS_DONT_OPEN_SCOPE,
795                        WalkState, &Node);
796 #endif
797         }
798     }
799
800     /*
801      * Found the node in external table, add it to external list
802      * Node->OwnerId == 0 indicates built-in ACPI Names, _OS_ etc
803      */
804     else if (Node->OwnerId && WalkState->OwnerId != Node->OwnerId)
805     {
806         ObjectType2 = ObjectType;
807
808         Object = AcpiNsGetAttachedObject (Node);
809         if (Object)
810         {
811             ObjectType2 = Object->Common.Type;
812             if (ObjectType2 == ACPI_TYPE_METHOD)
813             {
814                 ParamCount = Object->Method.ParamCount;
815             }
816         }
817
818         AcpiDmAddToExternalList (Op, Path, (UINT8) ObjectType2, ParamCount);
819         Op->Common.Node = Node;
820     }
821     else
822     {
823         Op->Common.Node = Node;
824     }
825
826
827 Exit:
828     /* Open new scope if necessary */
829
830     if (AcpiNsOpensScope (ObjectType))
831     {
832         if (Op->Common.Node)
833         {
834             Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState);
835             if (ACPI_FAILURE (Status))
836             {
837                 return (Status);
838             }
839         }
840     }
841
842     return (AE_OK);
843 }
844
845
846 /*******************************************************************************
847  *
848  * FUNCTION:    AcpiDmResourceDescendingOp
849  *
850  * PARAMETERS:  ASL_WALK_CALLBACK
851  *
852  * RETURN:      None
853  *
854  * DESCRIPTION: Process one parse op during symbolic resource index conversion.
855  *
856  ******************************************************************************/
857
858 static ACPI_STATUS
859 AcpiDmResourceDescendingOp (
860     ACPI_PARSE_OBJECT       *Op,
861     UINT32                  Level,
862     void                    *Context)
863 {
864     ACPI_OP_WALK_INFO       *Info = Context;
865     const ACPI_OPCODE_INFO  *OpInfo;
866     ACPI_WALK_STATE         *WalkState;
867     ACPI_OBJECT_TYPE        ObjectType;
868     ACPI_STATUS             Status;
869
870
871     WalkState = Info->WalkState;
872     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
873
874     /* Open new scope if necessary */
875
876     ObjectType = OpInfo->ObjectType;
877     if (AcpiNsOpensScope (ObjectType))
878     {
879         if (Op->Common.Node)
880         {
881
882             Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState);
883             if (ACPI_FAILURE (Status))
884             {
885                 return (Status);
886             }
887         }
888     }
889
890     /*
891      * Check if this operator contains a reference to a resource descriptor.
892      * If so, convert the reference into a symbolic reference.
893      */
894     AcpiDmCheckResourceReference (Op, WalkState);
895     return (AE_OK);
896 }
897
898
899 /*******************************************************************************
900  *
901  * FUNCTION:    AcpiDmCommonAscendingOp
902  *
903  * PARAMETERS:  ASL_WALK_CALLBACK
904  *
905  * RETURN:      None
906  *
907  * DESCRIPTION: Ascending handler for combined parse/namespace walks. Closes
908  *              scope if necessary.
909  *
910  ******************************************************************************/
911
912 static ACPI_STATUS
913 AcpiDmCommonAscendingOp (
914     ACPI_PARSE_OBJECT       *Op,
915     UINT32                  Level,
916     void                    *Context)
917 {
918     ACPI_OP_WALK_INFO       *Info = Context;
919     const ACPI_OPCODE_INFO  *OpInfo;
920     ACPI_OBJECT_TYPE        ObjectType;
921
922
923     /* Close scope if necessary */
924
925     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
926     ObjectType = OpInfo->ObjectType;
927     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
928
929     if (AcpiNsOpensScope (ObjectType))
930     {
931         (void) AcpiDsScopeStackPop (Info->WalkState);
932     }
933
934     return (AE_OK);
935 }
936
937
938 /*******************************************************************************
939  *
940  * FUNCTION:    AcpiDmInspectPossibleArgs
941  *
942  * PARAMETERS:  CurrentOpArgCount   - Which arg of the current op was the
943  *                                    possible method invocation found
944  *              TargetCount         - Number of targets (0,1,2) for this op
945  *              Op                  - Parse op
946  *
947  * RETURN:      Status
948  *
949  * DESCRIPTION: Examine following args and next ops for possible arguments
950  *              for an unrecognized method invocation.
951  *
952  ******************************************************************************/
953
954 static UINT32
955 AcpiDmInspectPossibleArgs (
956     UINT32                  CurrentOpArgCount,
957     UINT32                  TargetCount,
958     ACPI_PARSE_OBJECT       *Op)
959 {
960     const ACPI_OPCODE_INFO  *OpInfo;
961     UINT32                  i;
962     UINT32                  Last = 0;
963     UINT32                  Lookahead;
964
965
966     Lookahead = (ACPI_METHOD_NUM_ARGS + TargetCount) - CurrentOpArgCount;
967
968     /* Lookahead for the maximum number of possible arguments */
969
970     for (i = 0; i < Lookahead; i++)
971     {
972         if (!Op)
973         {
974             break;
975         }
976
977         OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
978
979         /*
980          * Any one of these operators is "very probably" not a method arg
981          */
982         if ((Op->Common.AmlOpcode == AML_STORE_OP) ||
983             (Op->Common.AmlOpcode == AML_NOTIFY_OP))
984         {
985             break;
986         }
987
988         if ((OpInfo->Class != AML_CLASS_EXECUTE) &&
989             (OpInfo->Class != AML_CLASS_CONTROL))
990         {
991             Last = i+1;
992         }
993
994         Op = Op->Common.Next;
995     }
996
997     return (Last);
998 }
999
1000