xref: /netbsd-src/sys/external/bsd/acpica/dist/common/adwalk.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /******************************************************************************
2  *
3  * Module Name: adwalk - Application-level disassembler parse tree walk routines
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2018, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include "acpi.h"
45 #include "accommon.h"
46 #include "acparser.h"
47 #include "amlcode.h"
48 #include "acdisasm.h"
49 #include "acdispat.h"
50 #include "acnamesp.h"
51 #include "acapps.h"
52 
53 
54 #define _COMPONENT          ACPI_TOOLS
55         ACPI_MODULE_NAME    ("adwalk")
56 
57 /*
58  * aslmap - opcode mappings and reserved method names
59  */
60 ACPI_OBJECT_TYPE
61 AslMapNamedOpcodeToDataType (
62     UINT16                  Opcode);
63 
64 /* Local prototypes */
65 
66 static ACPI_STATUS
67 AcpiDmFindOrphanDescending (
68     ACPI_PARSE_OBJECT       *Op,
69     UINT32                  Level,
70     void                    *Context);
71 
72 static ACPI_STATUS
73 AcpiDmDumpDescending (
74     ACPI_PARSE_OBJECT       *Op,
75     UINT32                  Level,
76     void                    *Context);
77 
78 static ACPI_STATUS
79 AcpiDmXrefDescendingOp (
80     ACPI_PARSE_OBJECT       *Op,
81     UINT32                  Level,
82     void                    *Context);
83 
84 static ACPI_STATUS
85 AcpiDmCommonAscendingOp (
86     ACPI_PARSE_OBJECT       *Op,
87     UINT32                  Level,
88     void                    *Context);
89 
90 static ACPI_STATUS
91 AcpiDmLoadDescendingOp (
92     ACPI_PARSE_OBJECT       *Op,
93     UINT32                  Level,
94     void                    *Context);
95 
96 static UINT32
97 AcpiDmInspectPossibleArgs (
98     UINT32                  CurrentOpArgCount,
99     UINT32                  TargetCount,
100     ACPI_PARSE_OBJECT       *Op);
101 
102 static ACPI_STATUS
103 AcpiDmCommonDescendingOp (
104     ACPI_PARSE_OBJECT       *Op,
105     UINT32                  Level,
106     void                    *Context);
107 
108 static ACPI_STATUS
109 AcpiDmProcessResourceDescriptors (
110     ACPI_PARSE_OBJECT       *Op,
111     UINT32                  Level,
112     void                    *Context);
113 
114 /*******************************************************************************
115  *
116  * FUNCTION:    AcpiDmDumpTree
117  *
118  * PARAMETERS:  Origin              - Starting object
119  *
120  * RETURN:      None
121  *
122  * DESCRIPTION: Parse tree walk to format and output the nodes
123  *
124  ******************************************************************************/
125 
126 void
127 AcpiDmDumpTree (
128     ACPI_PARSE_OBJECT       *Origin)
129 {
130     ACPI_OP_WALK_INFO       Info;
131 
132 
133     if (!Origin)
134     {
135         return;
136     }
137 
138     AcpiOsPrintf ("/*\nAML Parse Tree\n\n");
139     Info.Flags = 0;
140     Info.Count = 0;
141     Info.Level = 0;
142     Info.WalkState = NULL;
143 
144     AcpiDmWalkParseTree (Origin, AcpiDmDumpDescending, NULL, &Info);
145     AcpiOsPrintf ("*/\n\n");
146 }
147 
148 
149 /*******************************************************************************
150  *
151  * FUNCTION:    AcpiDmFindOrphanMethods
152  *
153  * PARAMETERS:  Origin              - Starting object
154  *
155  * RETURN:      None
156  *
157  * DESCRIPTION: Parse tree walk to find "orphaned" method invocations -- methods
158  *              that are not resolved in the namespace
159  *
160  ******************************************************************************/
161 
162 void
163 AcpiDmFindOrphanMethods (
164     ACPI_PARSE_OBJECT       *Origin)
165 {
166     ACPI_OP_WALK_INFO       Info;
167 
168 
169     if (!Origin)
170     {
171         return;
172     }
173 
174     Info.Flags = 0;
175     Info.Level = 0;
176     Info.WalkState = NULL;
177 
178     AcpiDmWalkParseTree (Origin, AcpiDmFindOrphanDescending, NULL, &Info);
179 }
180 
181 
182 /*******************************************************************************
183  *
184  * FUNCTION:    AcpiDmFinishNamespaceLoad
185  *
186  * PARAMETERS:  ParseTreeRoot       - Root of the parse tree
187  *              NamespaceRoot       - Root of the internal namespace
188  *              OwnerId             - OwnerId of the table to be disassembled
189  *
190  * RETURN:      None
191  *
192  * DESCRIPTION: Load all namespace items that are created within control
193  *              methods. Used before namespace cross reference
194  *
195  ******************************************************************************/
196 
197 void
198 AcpiDmFinishNamespaceLoad (
199     ACPI_PARSE_OBJECT       *ParseTreeRoot,
200     ACPI_NAMESPACE_NODE     *NamespaceRoot,
201     ACPI_OWNER_ID           OwnerId)
202 {
203     ACPI_STATUS             Status;
204     ACPI_OP_WALK_INFO       Info;
205     ACPI_WALK_STATE         *WalkState;
206 
207 
208     if (!ParseTreeRoot)
209     {
210         return;
211     }
212 
213     /* Create and initialize a new walk state */
214 
215     WalkState = AcpiDsCreateWalkState (OwnerId, ParseTreeRoot, NULL, NULL);
216     if (!WalkState)
217     {
218         return;
219     }
220 
221     Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type,
222         WalkState);
223     if (ACPI_FAILURE (Status))
224     {
225         return;
226     }
227 
228     Info.Flags = 0;
229     Info.Level = 0;
230     Info.WalkState = WalkState;
231 
232     AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmLoadDescendingOp,
233         AcpiDmCommonAscendingOp, &Info);
234     ACPI_FREE (WalkState);
235 }
236 
237 
238 /*******************************************************************************
239  *
240  * FUNCTION:    AcpiDmCrossReferenceNamespace
241  *
242  * PARAMETERS:  ParseTreeRoot       - Root of the parse tree
243  *              NamespaceRoot       - Root of the internal namespace
244  *              OwnerId             - OwnerId of the table to be disassembled
245  *
246  * RETURN:      None
247  *
248  * DESCRIPTION: Cross reference the namespace to create externals
249  *
250  ******************************************************************************/
251 
252 void
253 AcpiDmCrossReferenceNamespace (
254     ACPI_PARSE_OBJECT       *ParseTreeRoot,
255     ACPI_NAMESPACE_NODE     *NamespaceRoot,
256     ACPI_OWNER_ID           OwnerId)
257 {
258     ACPI_STATUS             Status;
259     ACPI_OP_WALK_INFO       Info;
260     ACPI_WALK_STATE         *WalkState;
261 
262 
263     if (!ParseTreeRoot)
264     {
265         return;
266     }
267 
268     /* Create and initialize a new walk state */
269 
270     WalkState = AcpiDsCreateWalkState (OwnerId, ParseTreeRoot, NULL, NULL);
271     if (!WalkState)
272     {
273         return;
274     }
275 
276     Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type,
277         WalkState);
278     if (ACPI_FAILURE (Status))
279     {
280         return;
281     }
282 
283     Info.Flags = 0;
284     Info.Level = 0;
285     Info.WalkState = WalkState;
286 
287     AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmXrefDescendingOp,
288         AcpiDmCommonAscendingOp, &Info);
289     ACPI_FREE (WalkState);
290 }
291 
292 
293 /*******************************************************************************
294  *
295  * FUNCTION:    AcpiDmConvertParseObjects
296  *
297  * PARAMETERS:  ParseTreeRoot       - Root of the parse tree
298  *              NamespaceRoot       - Root of the internal namespace
299  *
300  * RETURN:      None
301  *
302  * DESCRIPTION: Begin parse tree walk to perform conversions needed for
303  *              disassembly. These include resource descriptors and switch/case
304  *              operations.
305  *
306  ******************************************************************************/
307 
308 void
309 AcpiDmConvertParseObjects (
310     ACPI_PARSE_OBJECT       *ParseTreeRoot,
311     ACPI_NAMESPACE_NODE     *NamespaceRoot)
312 {
313     ACPI_STATUS             Status;
314     ACPI_OP_WALK_INFO       Info;
315     ACPI_WALK_STATE         *WalkState;
316 
317 
318     if (!ParseTreeRoot)
319     {
320         return;
321     }
322 
323     /* Create and initialize a new walk state */
324 
325     WalkState = AcpiDsCreateWalkState (0, ParseTreeRoot, NULL, NULL);
326     if (!WalkState)
327     {
328         return;
329     }
330 
331     Status = AcpiDsScopeStackPush (NamespaceRoot, NamespaceRoot->Type,
332         WalkState);
333     if (ACPI_FAILURE (Status))
334     {
335         ACPI_FREE (WalkState);
336         return;
337     }
338 
339     Info.Flags = 0;
340     Info.Level = 0;
341     Info.WalkState = WalkState;
342 
343     AcpiDmWalkParseTree (ParseTreeRoot, AcpiDmCommonDescendingOp,
344         AcpiDmCommonAscendingOp, &Info);
345     ACPI_FREE (WalkState);
346 
347     if (AcpiGbl_TempListHead) {
348         AcpiDmClearTempList();
349     }
350 
351     return;
352 }
353 
354 
355 /*******************************************************************************
356  *
357  * FUNCTION:    AcpiDmDumpDescending
358  *
359  * PARAMETERS:  ASL_WALK_CALLBACK
360  *
361  * RETURN:      Status
362  *
363  * DESCRIPTION: Format and print contents of one parse Op.
364  *
365  ******************************************************************************/
366 
367 static ACPI_STATUS
368 AcpiDmDumpDescending (
369     ACPI_PARSE_OBJECT       *Op,
370     UINT32                  Level,
371     void                    *Context)
372 {
373     ACPI_OP_WALK_INFO       *Info = Context;
374     char                    *Path;
375 
376 
377     if (!Op)
378     {
379         return (AE_OK);
380     }
381 
382     /* Most of the information (count, level, name) here */
383 
384     Info->Count++;
385     AcpiOsPrintf ("% 5d [%2.2d] ", Info->Count, Level);
386     AcpiDmIndent (Level);
387     AcpiOsPrintf ("%-28s", AcpiPsGetOpcodeName (Op->Common.AmlOpcode));
388 
389     /* Extra info is helpful */
390 
391     switch (Op->Common.AmlOpcode)
392     {
393     case AML_BYTE_OP:
394 
395         AcpiOsPrintf ("%2.2X", (UINT32) Op->Common.Value.Integer);
396         break;
397 
398     case AML_WORD_OP:
399 
400         AcpiOsPrintf ("%4.4X", (UINT32) Op->Common.Value.Integer);
401         break;
402 
403     case AML_DWORD_OP:
404 
405         AcpiOsPrintf ("%8.8X", (UINT32) Op->Common.Value.Integer);
406         break;
407 
408     case AML_QWORD_OP:
409 
410         AcpiOsPrintf ("%8.8X%8.8X", ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
411         break;
412 
413     case AML_INT_NAMEPATH_OP:
414 
415         if (Op->Common.Value.String)
416         {
417             AcpiNsExternalizeName (ACPI_UINT32_MAX, Op->Common.Value.String,
418                 NULL, &Path);
419             AcpiOsPrintf ("%s %p", Path, Op->Common.Node);
420             ACPI_FREE (Path);
421         }
422         else
423         {
424             AcpiOsPrintf ("[NULL]");
425         }
426         break;
427 
428     case AML_NAME_OP:
429     case AML_METHOD_OP:
430     case AML_DEVICE_OP:
431 
432         AcpiOsPrintf ("%4.4s",
433             ACPI_CAST_PTR (char, &Op->Named.Name));
434         break;
435 
436     case AML_INT_NAMEDFIELD_OP:
437 
438         AcpiOsPrintf ("%4.4s Length: (bits) %8.8X%8.8X (bytes) %8.8X%8.8X",
439             ACPI_CAST_PTR (char, &Op->Named.Name),
440             ACPI_FORMAT_UINT64 (Op->Common.Value.Integer),
441             ACPI_FORMAT_UINT64 (Op->Common.Value.Integer / 8));
442         break;
443 
444 
445     default:
446 
447         break;
448     }
449 
450     AcpiOsPrintf ("\n");
451     return (AE_OK);
452 }
453 
454 
455 /*******************************************************************************
456  *
457  * FUNCTION:    AcpiDmFindOrphanDescending
458  *
459  * PARAMETERS:  ASL_WALK_CALLBACK
460  *
461  * RETURN:      Status
462  *
463  * DESCRIPTION: Check namepath Ops for orphaned method invocations
464  *
465  * Note: Parts of this are experimental, under possible further development.
466  *
467  ******************************************************************************/
468 
469 static ACPI_STATUS
470 AcpiDmFindOrphanDescending (
471     ACPI_PARSE_OBJECT       *Op,
472     UINT32                  Level,
473     void                    *Context)
474 {
475     const ACPI_OPCODE_INFO  *OpInfo;
476     ACPI_PARSE_OBJECT       *ChildOp;
477     ACPI_PARSE_OBJECT       *NextOp;
478     ACPI_PARSE_OBJECT       *ParentOp;
479     UINT32                  ArgCount;
480 
481 
482     if (!Op)
483     {
484         return (AE_OK);
485     }
486 
487     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
488 
489     switch (Op->Common.AmlOpcode)
490     {
491 #ifdef ACPI_UNDER_DEVELOPMENT
492     case AML_ADD_OP:
493 
494         ChildOp = Op->Common.Value.Arg;
495         if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
496             !ChildOp->Common.Node)
497         {
498             AcpiNsExternalizeName (ACPI_UINT32_MAX, ChildOp->Common.Value.String,
499                 NULL, &Path);
500             AcpiOsPrintf ("/* %-16s A-NAMEPATH: %s  */\n",
501                 Op->Common.AmlOpName, Path);
502             ACPI_FREE (Path);
503 
504             NextOp = Op->Common.Next;
505             if (!NextOp)
506             {
507                 /* This NamePath has no args, assume it is an integer */
508 
509                 AcpiDmAddOpToExternalList (ChildOp,
510                     ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
511                 return (AE_OK);
512             }
513 
514             ArgCount = AcpiDmInspectPossibleArgs (3, 1, NextOp);
515             AcpiOsPrintf ("/* A-CHILDREN: %u Actual %u */\n",
516                 ArgCount, AcpiDmCountChildren (Op));
517 
518             if (ArgCount < 1)
519             {
520                 /* One Arg means this is just a Store(Name,Target) */
521 
522                 AcpiDmAddOpToExternalList (ChildOp,
523                     ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
524                 return (AE_OK);
525             }
526 
527             AcpiDmAddOpToExternalList (ChildOp,
528                 ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0);
529         }
530         break;
531 
532 #endif
533 
534     case AML_STORE_OP:
535 
536         ChildOp = Op->Common.Value.Arg;
537         if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
538             !ChildOp->Common.Node)
539         {
540             NextOp = Op->Common.Next;
541             if (!NextOp)
542             {
543                 /* This NamePath has no args, assume it is an integer */
544 
545                 AcpiDmAddOpToExternalList (ChildOp,
546                     ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
547                 return (AE_OK);
548             }
549 
550             ArgCount = AcpiDmInspectPossibleArgs (2, 1, NextOp);
551             if (ArgCount <= 1)
552             {
553                 /* One Arg means this is just a Store(Name,Target) */
554 
555                 AcpiDmAddOpToExternalList (ChildOp,
556                     ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, ArgCount, 0);
557                 return (AE_OK);
558             }
559 
560             AcpiDmAddOpToExternalList (ChildOp,
561                 ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0);
562         }
563         break;
564 
565     case AML_INT_NAMEPATH_OP:
566 
567         /* Must examine parent to see if this namepath is an argument */
568 
569         ParentOp = Op->Common.Parent;
570         OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode);
571 
572         if ((OpInfo->Class != AML_CLASS_EXECUTE) &&
573             (OpInfo->Class != AML_CLASS_CREATE) &&
574             (OpInfo->ObjectType != ACPI_TYPE_LOCAL_ALIAS) &&
575             (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) &&
576             !Op->Common.Node)
577         {
578             ArgCount = AcpiDmInspectPossibleArgs (0, 0, Op);
579 
580             /*
581              * Check if namepath is a predicate for if/while or lone parameter to
582              * a return.
583              */
584             if (ArgCount == 0)
585             {
586                 if (((ParentOp->Common.AmlOpcode == AML_IF_OP) ||
587                      (ParentOp->Common.AmlOpcode == AML_WHILE_OP) ||
588                      (ParentOp->Common.AmlOpcode == AML_RETURN_OP)) &&
589 
590                      /* And namepath is the first argument */
591                      (ParentOp->Common.Value.Arg == Op))
592                 {
593                     AcpiDmAddOpToExternalList (Op,
594                         Op->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
595                     break;
596                 }
597             }
598 
599             /*
600              * This is a standalone namestring (not a parameter to another
601              * operator) - it *must* be a method invocation, nothing else is
602              * grammatically possible.
603              */
604             AcpiDmAddOpToExternalList (Op,
605                 Op->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0);
606         }
607         break;
608 
609     default:
610 
611         break;
612     }
613 
614     return (AE_OK);
615 }
616 
617 
618 /*******************************************************************************
619  *
620  * FUNCTION:    AcpiDmLoadDescendingOp
621  *
622  * PARAMETERS:  ASL_WALK_CALLBACK
623  *
624  * RETURN:      Status
625  *
626  * DESCRIPTION: Descending handler for namespace control method object load
627  *
628  ******************************************************************************/
629 
630 static ACPI_STATUS
631 AcpiDmLoadDescendingOp (
632     ACPI_PARSE_OBJECT       *Op,
633     UINT32                  Level,
634     void                    *Context)
635 {
636     ACPI_OP_WALK_INFO       *Info = Context;
637     const ACPI_OPCODE_INFO  *OpInfo;
638     ACPI_WALK_STATE         *WalkState;
639     ACPI_OBJECT_TYPE        ObjectType;
640     ACPI_STATUS             Status;
641     char                    *Path = NULL;
642     ACPI_PARSE_OBJECT       *NextOp;
643     ACPI_NAMESPACE_NODE     *Node;
644     char                    FieldPath[5];
645     BOOLEAN                 PreDefined = FALSE;
646     UINT8                   PreDefineIndex = 0;
647 
648 
649     WalkState = Info->WalkState;
650     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
651     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
652 
653     /* Only interested in operators that create new names */
654 
655     if (!(OpInfo->Flags & AML_NAMED) &&
656         !(OpInfo->Flags & AML_CREATE))
657     {
658         goto Exit;
659     }
660 
661     /* Get the NamePath from the appropriate place */
662 
663     if (OpInfo->Flags & AML_NAMED)
664     {
665         /* For all named operators, get the new name */
666 
667         Path = Op->Named.Path;
668 
669         if (!Path && Op->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP)
670         {
671             *ACPI_CAST_PTR (UINT32, &FieldPath[0]) = Op->Named.Name;
672             FieldPath[4] = 0;
673             Path = FieldPath;
674         }
675     }
676     else if (OpInfo->Flags & AML_CREATE)
677     {
678         /* New name is the last child */
679 
680         NextOp = Op->Common.Value.Arg;
681 
682         while (NextOp->Common.Next)
683         {
684             NextOp = NextOp->Common.Next;
685         }
686 
687         Path = NextOp->Common.Value.String;
688     }
689 
690     if (!Path)
691     {
692         goto Exit;
693     }
694 
695     /* Insert the name into the namespace */
696 
697     Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
698         ACPI_IMODE_LOAD_PASS2, ACPI_NS_DONT_OPEN_SCOPE,
699         WalkState, &Node);
700 
701     Op->Common.Node = Node;
702 
703     if (ACPI_SUCCESS (Status))
704     {
705         /* Check if it's a predefined node */
706 
707         while (AcpiGbl_PreDefinedNames[PreDefineIndex].Name)
708         {
709             if (ACPI_COMPARE_NAME (Node->Name.Ascii,
710                 AcpiGbl_PreDefinedNames[PreDefineIndex].Name))
711             {
712                 PreDefined = TRUE;
713                 break;
714             }
715 
716             PreDefineIndex++;
717         }
718 
719         /*
720          * Set node owner id if it satisfies all the following conditions:
721          * 1) Not a predefined node, _SB_ etc
722          * 2) Not the root node
723          * 3) Not a node created by Scope
724          */
725 
726         if (!PreDefined && Node != AcpiGbl_RootNode &&
727             Op->Common.AmlOpcode != AML_SCOPE_OP)
728         {
729             Node->OwnerId = WalkState->OwnerId;
730         }
731     }
732 
733 
734 Exit:
735 
736     if (AcpiNsOpensScope (ObjectType))
737     {
738         if (Op->Common.Node)
739         {
740             Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType,
741                 WalkState);
742             if (ACPI_FAILURE (Status))
743             {
744                 return (Status);
745             }
746         }
747     }
748 
749     return (AE_OK);
750 }
751 
752 
753 /*******************************************************************************
754  *
755  * FUNCTION:    AcpiDmXrefDescendingOp
756  *
757  * PARAMETERS:  ASL_WALK_CALLBACK
758  *
759  * RETURN:      Status
760  *
761  * DESCRIPTION: Descending handler for namespace cross reference
762  *
763  ******************************************************************************/
764 
765 static ACPI_STATUS
766 AcpiDmXrefDescendingOp (
767     ACPI_PARSE_OBJECT       *Op,
768     UINT32                  Level,
769     void                    *Context)
770 {
771     ACPI_OP_WALK_INFO       *Info = Context;
772     const ACPI_OPCODE_INFO  *OpInfo;
773     ACPI_WALK_STATE         *WalkState;
774     ACPI_OBJECT_TYPE        ObjectType;
775     ACPI_OBJECT_TYPE        ObjectType2;
776     ACPI_STATUS             Status;
777     char                    *Path = NULL;
778     ACPI_PARSE_OBJECT       *NextOp;
779     ACPI_NAMESPACE_NODE     *Node;
780     ACPI_OPERAND_OBJECT     *Object;
781     UINT32                  ParamCount = 0;
782     char                    *Pathname;
783     UINT16                  Flags = 0;
784 
785 
786     WalkState = Info->WalkState;
787     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
788     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
789 
790     if ((!(OpInfo->Flags & AML_NAMED)) &&
791         (!(OpInfo->Flags & AML_CREATE)) &&
792         (Op->Common.AmlOpcode != AML_INT_NAMEPATH_OP) &&
793         (Op->Common.AmlOpcode != AML_NOTIFY_OP))
794     {
795         goto Exit;
796     }
797 
798     /* Get the NamePath from the appropriate place */
799 
800     if (OpInfo->Flags & AML_NAMED)
801     {
802         /*
803          * Only these two operators (Alias, Scope) refer to an existing
804          * name, it is the first argument
805          */
806         if (Op->Common.AmlOpcode == AML_ALIAS_OP)
807         {
808             ObjectType = ACPI_TYPE_ANY;
809 
810             NextOp = Op->Common.Value.Arg;
811             NextOp = NextOp->Common.Value.Arg;
812             if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
813             {
814                 Path = NextOp->Common.Value.String;
815             }
816         }
817         else if (Op->Common.AmlOpcode == AML_SCOPE_OP ||
818                  Op->Common.AmlOpcode == AML_EXTERNAL_OP)
819         {
820             Path = Op->Named.Path;
821         }
822     }
823     else if (OpInfo->Flags & AML_CREATE)
824     {
825         /* Referenced Buffer Name is the first child */
826 
827         ObjectType = ACPI_TYPE_BUFFER; /* Change from TYPE_BUFFER_FIELD */
828 
829         NextOp = Op->Common.Value.Arg;
830         if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
831         {
832             Path = NextOp->Common.Value.String;
833         }
834     }
835     else if (Op->Common.AmlOpcode == AML_NOTIFY_OP)
836     {
837         Path = Op->Common.Value.Arg->Asl.Value.String;
838     }
839     else
840     {
841         Path = Op->Common.Value.String;
842     }
843 
844     if (!Path)
845     {
846         goto Exit;
847     }
848 
849     /*
850      * Lookup the name in the namespace. Name must exist at this point, or it
851      * is an invalid reference.
852      *
853      * The namespace is also used as a lookup table for references to resource
854      * descriptors and the fields within them.
855      */
856     Node = NULL;
857     Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY,
858         ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
859         WalkState, &Node);
860 
861     if (ACPI_SUCCESS (Status) && (Node->Flags & ANOBJ_IS_EXTERNAL))
862     {
863         /* Node was created by an External() statement */
864 
865         Status = AE_NOT_FOUND;
866     }
867 
868     if (ACPI_FAILURE (Status))
869     {
870         if (Status == AE_NOT_FOUND)
871         {
872             /*
873              * Add this symbol as an external declaration, except if the
874              * parent is a CondRefOf operator. For this operator, we do not
875              * need an external, nor do we want one, since this can cause
876              * disassembly problems if the symbol is actually a control
877              * method.
878              */
879             if (!(Op->Asl.Parent &&
880                 (Op->Asl.Parent->Asl.AmlOpcode == AML_CONDITIONAL_REF_OF_OP)))
881             {
882                 if (Node)
883                 {
884                     AcpiDmAddNodeToExternalList (Node,
885                         (UINT8) ObjectType, 7, Flags);
886                 }
887                 else
888                 {
889                     AcpiDmAddOpToExternalList (Op, Path,
890                         (UINT8) ObjectType, 7, Flags);
891                 }
892             }
893         }
894     }
895 
896     /*
897      * Found the node, but check if it came from an external table.
898      * Add it to external list. Note: Node->OwnerId == 0 indicates
899      * one of the built-in ACPI Names (_OS_ etc.) which can safely
900      * be ignored.
901      */
902     else if (Node->OwnerId &&
903             (WalkState->OwnerId != Node->OwnerId))
904     {
905         ObjectType2 = ObjectType;
906 
907         Object = AcpiNsGetAttachedObject (Node);
908         if (Object)
909         {
910             ObjectType2 = Object->Common.Type;
911             if (ObjectType2 == ACPI_TYPE_METHOD)
912             {
913                 ParamCount = Object->Method.ParamCount;
914             }
915         }
916 
917         Pathname = AcpiNsGetExternalPathname (Node);
918         if (!Pathname)
919         {
920             return (AE_NO_MEMORY);
921         }
922 
923         AcpiDmAddNodeToExternalList (Node, (UINT8) ObjectType2,
924             ParamCount, ACPI_EXT_RESOLVED_REFERENCE);
925 
926         ACPI_FREE (Pathname);
927         Op->Common.Node = Node;
928     }
929     else
930     {
931         Op->Common.Node = Node;
932     }
933 
934 
935 Exit:
936     /* Open new scope if necessary */
937 
938     if (AcpiNsOpensScope (ObjectType))
939     {
940         if (Op->Common.Node)
941         {
942             Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType,
943                 WalkState);
944             if (ACPI_FAILURE (Status))
945             {
946                 return (Status);
947             }
948         }
949     }
950 
951     return (AE_OK);
952 }
953 
954 /*******************************************************************************
955  *
956  * FUNCTION:    AcpiDmCommonDescendingOp
957  *
958  * PARAMETERS:  ASL_WALK_CALLBACK
959  *
960  * RETURN:      ACPI_STATUS
961  *
962  * DESCRIPTION: Perform parse tree preprocessing before main disassembly walk.
963  *
964  ******************************************************************************/
965 
966 static ACPI_STATUS
967 AcpiDmCommonDescendingOp (
968     ACPI_PARSE_OBJECT       *Op,
969     UINT32                  Level,
970     void                    *Context)
971 {
972     ACPI_STATUS             Status;
973 
974 
975     /* Resource descriptor conversion */
976 
977     Status = AcpiDmProcessResourceDescriptors (Op, Level, Context);
978     if (ACPI_FAILURE (Status))
979     {
980         return (Status);
981     }
982 
983     /* Switch/Case conversion */
984 
985     Status = AcpiDmProcessSwitch (Op);
986     return (AE_OK);
987 }
988 
989 
990 /*******************************************************************************
991  *
992  * FUNCTION:    AcpiDmProcessResourceDescriptors
993  *
994  * PARAMETERS:  ASL_WALK_CALLBACK
995  *
996  * RETURN:      ACPI_STATUS
997  *
998  * DESCRIPTION: Convert fixed-offset references to resource descriptors to
999  *              symbolic references. Should only be called after namespace has
1000  *              been cross referenced.
1001  *
1002  ******************************************************************************/
1003 
1004 static ACPI_STATUS
1005 AcpiDmProcessResourceDescriptors (
1006     ACPI_PARSE_OBJECT       *Op,
1007     UINT32                  Level,
1008     void                    *Context)
1009 {
1010     ACPI_OP_WALK_INFO       *Info = Context;
1011     const ACPI_OPCODE_INFO  *OpInfo;
1012     ACPI_WALK_STATE         *WalkState;
1013     ACPI_OBJECT_TYPE        ObjectType;
1014     ACPI_STATUS             Status;
1015 
1016 
1017     WalkState = Info->WalkState;
1018     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
1019 
1020     /* Open new scope if necessary */
1021 
1022     ObjectType = OpInfo->ObjectType;
1023     if (AcpiNsOpensScope (ObjectType))
1024     {
1025         if (Op->Common.Node)
1026         {
1027 
1028             Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType,
1029                 WalkState);
1030             if (ACPI_FAILURE (Status))
1031             {
1032                 return (Status);
1033             }
1034         }
1035     }
1036 
1037     /*
1038      * Check if this operator contains a reference to a resource descriptor.
1039      * If so, convert the reference into a symbolic reference.
1040      */
1041     AcpiDmCheckResourceReference (Op, WalkState);
1042     return (AE_OK);
1043 }
1044 
1045 /*******************************************************************************
1046  *
1047  * FUNCTION:    AcpiDmCommonAscendingOp
1048  *
1049  * PARAMETERS:  ASL_WALK_CALLBACK
1050  *
1051  * RETURN:      None
1052  *
1053  * DESCRIPTION: Ascending handler for combined parse/namespace walks. Closes
1054  *              scope if necessary.
1055  *
1056  ******************************************************************************/
1057 
1058 static ACPI_STATUS
1059 AcpiDmCommonAscendingOp (
1060     ACPI_PARSE_OBJECT       *Op,
1061     UINT32                  Level,
1062     void                    *Context)
1063 {
1064     ACPI_OP_WALK_INFO       *Info = Context;
1065     ACPI_OBJECT_TYPE        ObjectType;
1066 
1067 
1068     /* Close scope if necessary */
1069 
1070     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
1071 
1072     if (AcpiNsOpensScope (ObjectType))
1073     {
1074         (void) AcpiDsScopeStackPop (Info->WalkState);
1075     }
1076 
1077     return (AE_OK);
1078 }
1079 
1080 /*******************************************************************************
1081  *
1082  * FUNCTION:    AcpiDmInspectPossibleArgs
1083  *
1084  * PARAMETERS:  CurrentOpArgCount   - Which arg of the current op was the
1085  *                                    possible method invocation found
1086  *              TargetCount         - Number of targets (0,1,2) for this op
1087  *              Op                  - Parse op
1088  *
1089  * RETURN:      Status
1090  *
1091  * DESCRIPTION: Examine following args and next ops for possible arguments
1092  *              for an unrecognized method invocation.
1093  *
1094  ******************************************************************************/
1095 
1096 static UINT32
1097 AcpiDmInspectPossibleArgs (
1098     UINT32                  CurrentOpArgCount,
1099     UINT32                  TargetCount,
1100     ACPI_PARSE_OBJECT       *Op)
1101 {
1102     const ACPI_OPCODE_INFO  *OpInfo;
1103     UINT32                  i;
1104     UINT32                  ArgumentCount = 0;
1105     ACPI_PARSE_OBJECT       *NextOp;
1106     ACPI_PARSE_OBJECT       *ExecuteOp;
1107 
1108 
1109     if (!Op)
1110     {
1111         return (0);
1112     }
1113 
1114     /* Lookahead for the maximum number of possible arguments */
1115 
1116     NextOp = Op->Common.Next;
1117 
1118     for (i = 0; (i < ACPI_METHOD_NUM_ARGS) && NextOp; i++)
1119     {
1120         OpInfo = AcpiPsGetOpcodeInfo (NextOp->Common.AmlOpcode);
1121 
1122         /* Any one of these operators is "very probably" not a method arg */
1123 
1124         if ((NextOp->Common.AmlOpcode == AML_STORE_OP) ||
1125             (NextOp->Common.AmlOpcode == AML_NOTIFY_OP) ||
1126             (OpInfo->Class == AML_CLASS_CONTROL) ||
1127             (OpInfo->Class == AML_CLASS_CREATE) ||
1128             (OpInfo->Class == AML_CLASS_NAMED_OBJECT))
1129         {
1130             break;
1131         }
1132 
1133         if (OpInfo->Class == AML_CLASS_EXECUTE)
1134         {
1135             /* Probable that this is method arg if there is no target */
1136 
1137             ExecuteOp = NextOp->Common.Value.Arg;
1138             while (ExecuteOp)
1139             {
1140                 if ((ExecuteOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
1141                     (ExecuteOp->Common.Value.Arg == NULL))
1142                 {
1143                     /* No target, could be a method arg */
1144 
1145                     break;
1146                 }
1147 
1148                 if (NextOp->Common.AmlOpcode == AML_REF_OF_OP)
1149                 {
1150                     break;
1151                 }
1152 
1153                 ExecuteOp = ExecuteOp->Common.Next;
1154             }
1155 
1156             if (!ExecuteOp)
1157             {
1158                 /* Has a target, not method arg */
1159 
1160                 return (ArgumentCount);
1161             }
1162         }
1163 
1164         ArgumentCount++;
1165         NextOp = NextOp->Common.Next;
1166     }
1167 
1168     return (ArgumentCount);
1169 }
1170