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