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