xref: /netbsd/sys/external/bsd/acpica/dist/common/adwalk.c (revision e5631441)
1 /******************************************************************************
2  *
3  * Module Name: adwalk - Application-level disassembler parse tree walk routines
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2022, 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 MERCHANTABILITY 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
AcpiDmDumpTree(ACPI_PARSE_OBJECT * Origin)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
AcpiDmFindOrphanMethods(ACPI_PARSE_OBJECT * Origin)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
AcpiDmFinishNamespaceLoad(ACPI_PARSE_OBJECT * ParseTreeRoot,ACPI_NAMESPACE_NODE * NamespaceRoot,ACPI_OWNER_ID OwnerId)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
AcpiDmCrossReferenceNamespace(ACPI_PARSE_OBJECT * ParseTreeRoot,ACPI_NAMESPACE_NODE * NamespaceRoot,ACPI_OWNER_ID OwnerId)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
AcpiDmConvertParseObjects(ACPI_PARSE_OBJECT * ParseTreeRoot,ACPI_NAMESPACE_NODE * NamespaceRoot)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
AcpiDmDumpDescending(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)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     ACPI_STATUS             Status;
376 
377 
378     if (!Op)
379     {
380         return (AE_OK);
381     }
382 
383     /* Most of the information (count, level, name) here */
384 
385     Info->Count++;
386     AcpiOsPrintf ("% 5d [%2.2d] ", Info->Count, Level);
387     AcpiDmIndent (Level);
388     AcpiOsPrintf ("%-28s", AcpiPsGetOpcodeName (Op->Common.AmlOpcode));
389 
390     /* Extra info is helpful */
391 
392     switch (Op->Common.AmlOpcode)
393     {
394     case AML_BYTE_OP:
395 
396         AcpiOsPrintf ("%2.2X", (UINT32) Op->Common.Value.Integer);
397         break;
398 
399     case AML_WORD_OP:
400 
401         AcpiOsPrintf ("%4.4X", (UINT32) Op->Common.Value.Integer);
402         break;
403 
404     case AML_DWORD_OP:
405 
406         AcpiOsPrintf ("%8.8X", (UINT32) Op->Common.Value.Integer);
407         break;
408 
409     case AML_QWORD_OP:
410 
411         AcpiOsPrintf ("%8.8X%8.8X", ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
412         break;
413 
414     case AML_INT_NAMEPATH_OP:
415 
416         if (Op->Common.Value.String)
417         {
418             Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Op->Common.Value.String,
419                 NULL, &Path);
420             if (ACPI_SUCCESS (Status))
421             {
422                 AcpiOsPrintf ("%s %p", Path, Op->Common.Node);
423                 ACPI_FREE (Path);
424             }
425             else
426             {
427                 AcpiOsPrintf ("Could not externalize pathname for node [%4.4s]",
428                     Op->Common.Node->Name.Ascii);
429             }
430         }
431         else
432         {
433             AcpiOsPrintf ("[NULL]");
434         }
435         break;
436 
437     case AML_NAME_OP:
438     case AML_METHOD_OP:
439     case AML_DEVICE_OP:
440 
441         AcpiOsPrintf ("%4.4s",
442             ACPI_CAST_PTR (char, &Op->Named.Name));
443         break;
444 
445     case AML_INT_NAMEDFIELD_OP:
446 
447         AcpiOsPrintf ("%4.4s Length: (bits) %8.8X%8.8X (bytes) %8.8X%8.8X",
448             ACPI_CAST_PTR (char, &Op->Named.Name),
449             ACPI_FORMAT_UINT64 (Op->Common.Value.Integer),
450             ACPI_FORMAT_UINT64 (Op->Common.Value.Integer / 8));
451         break;
452 
453 
454     default:
455 
456         break;
457     }
458 
459     AcpiOsPrintf ("\n");
460     return (AE_OK);
461 }
462 
463 
464 /*******************************************************************************
465  *
466  * FUNCTION:    AcpiDmFindOrphanDescending
467  *
468  * PARAMETERS:  ASL_WALK_CALLBACK
469  *
470  * RETURN:      Status
471  *
472  * DESCRIPTION: Check namepath Ops for orphaned method invocations
473  *
474  * Note: Parts of this are experimental, under possible further development.
475  *
476  ******************************************************************************/
477 
478 static ACPI_STATUS
AcpiDmFindOrphanDescending(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)479 AcpiDmFindOrphanDescending (
480     ACPI_PARSE_OBJECT       *Op,
481     UINT32                  Level,
482     void                    *Context)
483 {
484     const ACPI_OPCODE_INFO  *OpInfo;
485     ACPI_PARSE_OBJECT       *ChildOp;
486     ACPI_PARSE_OBJECT       *NextOp;
487     ACPI_PARSE_OBJECT       *ParentOp;
488     UINT32                  ArgCount;
489 
490 
491     if (!Op)
492     {
493         return (AE_OK);
494     }
495 
496 #ifdef ACPI_UNDER_DEVELOPMENT
497     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
498 #endif
499 
500     switch (Op->Common.AmlOpcode)
501     {
502 #ifdef ACPI_UNDER_DEVELOPMENT
503     case AML_ADD_OP:
504 
505         ChildOp = Op->Common.Value.Arg;
506         if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
507             !ChildOp->Common.Node)
508         {
509             AcpiNsExternalizeName (ACPI_UINT32_MAX, ChildOp->Common.Value.String,
510                 NULL, &Path);
511             AcpiOsPrintf ("/* %-16s A-NAMEPATH: %s  */\n",
512                 Op->Common.AmlOpName, Path);
513             ACPI_FREE (Path);
514 
515             NextOp = Op->Common.Next;
516             if (!NextOp)
517             {
518                 /* This NamePath has no args, assume it is an integer */
519 
520                 AcpiDmAddOpToExternalList (ChildOp,
521                     ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
522                 return (AE_OK);
523             }
524 
525             ArgCount = AcpiDmInspectPossibleArgs (3, 1, NextOp);
526             AcpiOsPrintf ("/* A-CHILDREN: %u Actual %u */\n",
527                 ArgCount, AcpiDmCountChildren (Op));
528 
529             if (ArgCount < 1)
530             {
531                 /* One Arg means this is just a Store(Name,Target) */
532 
533                 AcpiDmAddOpToExternalList (ChildOp,
534                     ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
535                 return (AE_OK);
536             }
537 
538             AcpiDmAddOpToExternalList (ChildOp,
539                 ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0);
540         }
541         break;
542 
543 #endif
544 
545     case AML_STORE_OP:
546 
547         ChildOp = Op->Common.Value.Arg;
548         if ((ChildOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
549             !ChildOp->Common.Node)
550         {
551             NextOp = Op->Common.Next;
552             if (!NextOp)
553             {
554                 /* This NamePath has no args, assume it is an integer */
555 
556                 AcpiDmAddOpToExternalList (ChildOp,
557                     ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
558                 return (AE_OK);
559             }
560 
561             ArgCount = AcpiDmInspectPossibleArgs (2, 1, NextOp);
562             if (ArgCount <= 1)
563             {
564                 /* One Arg means this is just a Store(Name,Target) */
565 
566                 AcpiDmAddOpToExternalList (ChildOp,
567                     ChildOp->Common.Value.String, ACPI_TYPE_INTEGER, ArgCount, 0);
568                 return (AE_OK);
569             }
570 
571             AcpiDmAddOpToExternalList (ChildOp,
572                 ChildOp->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0);
573         }
574         break;
575 
576     case AML_INT_NAMEPATH_OP:
577 
578         /* Must examine parent to see if this namepath is an argument */
579 
580         ParentOp = Op->Common.Parent;
581         OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode);
582 
583         if ((OpInfo->Class != AML_CLASS_EXECUTE) &&
584             (OpInfo->Class != AML_CLASS_CREATE) &&
585             (OpInfo->ObjectType != ACPI_TYPE_LOCAL_ALIAS) &&
586             (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) &&
587             !Op->Common.Node)
588         {
589             ArgCount = AcpiDmInspectPossibleArgs (0, 0, Op);
590 
591             /*
592              * Check if namepath is a predicate for if/while or lone parameter to
593              * a return.
594              */
595             if (ArgCount == 0)
596             {
597                 if (((ParentOp->Common.AmlOpcode == AML_IF_OP) ||
598                      (ParentOp->Common.AmlOpcode == AML_WHILE_OP) ||
599                      (ParentOp->Common.AmlOpcode == AML_RETURN_OP)) &&
600 
601                      /* And namepath is the first argument */
602                      (ParentOp->Common.Value.Arg == Op))
603                 {
604                     AcpiDmAddOpToExternalList (Op,
605                         Op->Common.Value.String, ACPI_TYPE_INTEGER, 0, 0);
606                     break;
607                 }
608             }
609 
610             /*
611              * This is a standalone namestring (not a parameter to another
612              * operator) - it *must* be a method invocation, nothing else is
613              * grammatically possible.
614              */
615             AcpiDmAddOpToExternalList (Op,
616                 Op->Common.Value.String, ACPI_TYPE_METHOD, ArgCount, 0);
617         }
618         break;
619 
620     default:
621 
622         break;
623     }
624 
625     return (AE_OK);
626 }
627 
628 
629 /*******************************************************************************
630  *
631  * FUNCTION:    AcpiDmLoadDescendingOp
632  *
633  * PARAMETERS:  ASL_WALK_CALLBACK
634  *
635  * RETURN:      Status
636  *
637  * DESCRIPTION: Descending handler for namespace control method object load
638  *
639  ******************************************************************************/
640 
641 static ACPI_STATUS
AcpiDmLoadDescendingOp(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)642 AcpiDmLoadDescendingOp (
643     ACPI_PARSE_OBJECT       *Op,
644     UINT32                  Level,
645     void                    *Context)
646 {
647     ACPI_OP_WALK_INFO       *Info = Context;
648     const ACPI_OPCODE_INFO  *OpInfo;
649     ACPI_WALK_STATE         *WalkState;
650     ACPI_OBJECT_TYPE        ObjectType;
651     ACPI_STATUS             Status;
652     char                    *Path = NULL;
653     ACPI_PARSE_OBJECT       *NextOp;
654     ACPI_NAMESPACE_NODE     *Node;
655     char                    FieldPath[5];
656     BOOLEAN                 PreDefined = FALSE;
657     UINT8                   PreDefineIndex = 0;
658 
659 
660     WalkState = Info->WalkState;
661     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
662     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
663 
664     /* Only interested in operators that create new names */
665 
666     if (!(OpInfo->Flags & AML_NAMED) &&
667         !(OpInfo->Flags & AML_CREATE))
668     {
669         goto Exit;
670     }
671 
672     /* Get the NamePath from the appropriate place */
673 
674     if (OpInfo->Flags & AML_NAMED)
675     {
676         /* For all named operators, get the new name */
677 
678         Path = Op->Named.Path;
679 
680         if (!Path && Op->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP)
681         {
682             *ACPI_CAST_PTR (UINT32, &FieldPath[0]) = Op->Named.Name;
683             FieldPath[4] = 0;
684             Path = FieldPath;
685         }
686     }
687     else if (OpInfo->Flags & AML_CREATE)
688     {
689         /* New name is the last child */
690 
691         NextOp = Op->Common.Value.Arg;
692 
693         while (NextOp->Common.Next)
694         {
695             NextOp = NextOp->Common.Next;
696         }
697 
698         Path = NextOp->Common.Value.String;
699     }
700 
701     if (!Path)
702     {
703         goto Exit;
704     }
705 
706     /* Insert the name into the namespace */
707 
708     Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
709         ACPI_IMODE_LOAD_PASS2, ACPI_NS_DONT_OPEN_SCOPE,
710         WalkState, &Node);
711 
712     Op->Common.Node = Node;
713 
714     if (ACPI_SUCCESS (Status))
715     {
716         /* Check if it's a predefined node */
717 
718         while (AcpiGbl_PreDefinedNames[PreDefineIndex].Name)
719         {
720             if (ACPI_COMPARE_NAMESEG (Node->Name.Ascii,
721                 AcpiGbl_PreDefinedNames[PreDefineIndex].Name))
722             {
723                 PreDefined = TRUE;
724                 break;
725             }
726 
727             PreDefineIndex++;
728         }
729 
730         /*
731          * Set node owner id if it satisfies all the following conditions:
732          * 1) Not a predefined node, _SB_ etc
733          * 2) Not the root node
734          * 3) Not a node created by Scope
735          */
736         if (!PreDefined &&
737             (Node != AcpiGbl_RootNode) &&
738             (Op->Common.AmlOpcode != AML_SCOPE_OP))
739         {
740             Node->OwnerId = WalkState->OwnerId;
741         }
742     }
743 
744 
745 Exit:
746 
747     if (AcpiNsOpensScope (ObjectType))
748     {
749         if (Op->Common.Node)
750         {
751             Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType,
752                 WalkState);
753             if (ACPI_FAILURE (Status))
754             {
755                 return (Status);
756             }
757         }
758     }
759 
760     return (AE_OK);
761 }
762 
763 
764 /*******************************************************************************
765  *
766  * FUNCTION:    AcpiDmXrefDescendingOp
767  *
768  * PARAMETERS:  ASL_WALK_CALLBACK
769  *
770  * RETURN:      Status
771  *
772  * DESCRIPTION: Descending handler for namespace cross reference
773  *
774  ******************************************************************************/
775 
776 static ACPI_STATUS
AcpiDmXrefDescendingOp(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)777 AcpiDmXrefDescendingOp (
778     ACPI_PARSE_OBJECT       *Op,
779     UINT32                  Level,
780     void                    *Context)
781 {
782     ACPI_OP_WALK_INFO       *Info = Context;
783     const ACPI_OPCODE_INFO  *OpInfo;
784     ACPI_WALK_STATE         *WalkState;
785     ACPI_OBJECT_TYPE        ObjectType;
786     ACPI_OBJECT_TYPE        ObjectType2;
787     ACPI_STATUS             Status;
788     char                    *Path = NULL;
789     ACPI_PARSE_OBJECT       *NextOp;
790     ACPI_NAMESPACE_NODE     *Node;
791     ACPI_OPERAND_OBJECT     *Object;
792     UINT32                  ParamCount = 0;
793     char                    *Pathname;
794     UINT16                  Flags = 0;
795 
796 
797     WalkState = Info->WalkState;
798     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
799     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
800 
801     if ((!(OpInfo->Flags & AML_NAMED)) &&
802         (!(OpInfo->Flags & AML_CREATE)) &&
803         (Op->Common.AmlOpcode != AML_INT_NAMEPATH_OP) &&
804         (Op->Common.AmlOpcode != AML_NOTIFY_OP))
805     {
806         goto Exit;
807     }
808 
809     /* Get the NamePath from the appropriate place */
810 
811     if (OpInfo->Flags & AML_NAMED)
812     {
813         /*
814          * Only these two operators (Alias, Scope) refer to an existing
815          * name, it is the first argument
816          */
817         if (Op->Common.AmlOpcode == AML_ALIAS_OP)
818         {
819             ObjectType = ACPI_TYPE_ANY;
820 
821             NextOp = Op->Common.Value.Arg;
822             NextOp = NextOp->Common.Value.Arg;
823             if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
824             {
825                 Path = NextOp->Common.Value.String;
826             }
827         }
828         else if (Op->Common.AmlOpcode == AML_SCOPE_OP ||
829                  Op->Common.AmlOpcode == AML_EXTERNAL_OP)
830         {
831             Path = Op->Named.Path;
832         }
833     }
834     else if (OpInfo->Flags & AML_CREATE)
835     {
836         /* Referenced Buffer Name is the first child */
837 
838         ObjectType = ACPI_TYPE_BUFFER; /* Change from TYPE_BUFFER_FIELD */
839 
840         NextOp = Op->Common.Value.Arg;
841         if (NextOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
842         {
843             Path = NextOp->Common.Value.String;
844         }
845     }
846     else if (Op->Common.AmlOpcode == AML_NOTIFY_OP)
847     {
848         Path = Op->Common.Value.Arg->Asl.Value.String;
849     }
850     else
851     {
852         Path = Op->Common.Value.String;
853     }
854 
855     if (!Path)
856     {
857         goto Exit;
858     }
859 
860     /*
861      * Lookup the name in the namespace. Name must exist at this point, or it
862      * is an invalid reference.
863      *
864      * The namespace is also used as a lookup table for references to resource
865      * descriptors and the fields within them.
866      */
867     Node = NULL;
868     Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY,
869         ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
870         WalkState, &Node);
871 
872     if (ACPI_SUCCESS (Status) && (Node->Flags & ANOBJ_IS_EXTERNAL))
873     {
874         /* Node was created by an External() statement */
875 
876         Status = AE_NOT_FOUND;
877     }
878 
879     if (ACPI_FAILURE (Status))
880     {
881         if (Status == AE_NOT_FOUND)
882         {
883             /*
884              * Add this symbol as an external declaration, except if the
885              * parent is a CondRefOf operator. For this operator, we do not
886              * need an external, nor do we want one, since this can cause
887              * disassembly problems if the symbol is actually a control
888              * method.
889              */
890             if (!(Op->Asl.Parent &&
891                 (Op->Asl.Parent->Asl.AmlOpcode == AML_CONDITIONAL_REF_OF_OP)))
892             {
893                 if (Node)
894                 {
895                     AcpiDmAddNodeToExternalList (Node,
896                         (UINT8) ObjectType, 7, Flags);
897                 }
898                 else
899                 {
900                     AcpiDmAddOpToExternalList (Op, Path,
901                         (UINT8) ObjectType, 7, Flags);
902                 }
903             }
904         }
905     }
906 
907     /*
908      * Found the node, but check if it came from an external table.
909      * Add it to external list. Note: Node->OwnerId == 0 indicates
910      * one of the built-in ACPI Names (_OS_ etc.) which can safely
911      * be ignored.
912      */
913     else if (Node->OwnerId &&
914             (WalkState->OwnerId != Node->OwnerId))
915     {
916         ObjectType2 = ObjectType;
917 
918         Object = AcpiNsGetAttachedObject (Node);
919         if (Object)
920         {
921             ObjectType2 = Object->Common.Type;
922             if (ObjectType2 == ACPI_TYPE_METHOD)
923             {
924                 ParamCount = Object->Method.ParamCount;
925             }
926         }
927 
928         Pathname = AcpiNsGetExternalPathname (Node);
929         if (!Pathname)
930         {
931             return (AE_NO_MEMORY);
932         }
933 
934         AcpiDmAddNodeToExternalList (Node, (UINT8) ObjectType2,
935             ParamCount, ACPI_EXT_RESOLVED_REFERENCE);
936 
937         ACPI_FREE (Pathname);
938         Op->Common.Node = Node;
939     }
940     else
941     {
942         Op->Common.Node = Node;
943     }
944 
945 
946 Exit:
947     /* Open new scope if necessary */
948 
949     if (AcpiNsOpensScope (ObjectType))
950     {
951         if (Op->Common.Node)
952         {
953             Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType,
954                 WalkState);
955             if (ACPI_FAILURE (Status))
956             {
957                 return (Status);
958             }
959         }
960     }
961 
962     return (AE_OK);
963 }
964 
965 /*******************************************************************************
966  *
967  * FUNCTION:    AcpiDmCommonDescendingOp
968  *
969  * PARAMETERS:  ASL_WALK_CALLBACK
970  *
971  * RETURN:      ACPI_STATUS
972  *
973  * DESCRIPTION: Perform parse tree preprocessing before main disassembly walk.
974  *
975  ******************************************************************************/
976 
977 static ACPI_STATUS
AcpiDmCommonDescendingOp(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)978 AcpiDmCommonDescendingOp (
979     ACPI_PARSE_OBJECT       *Op,
980     UINT32                  Level,
981     void                    *Context)
982 {
983     ACPI_STATUS             Status;
984 
985 
986     /* Resource descriptor conversion */
987 
988     Status = AcpiDmProcessResourceDescriptors (Op, Level, Context);
989     if (ACPI_FAILURE (Status))
990     {
991         return (Status);
992     }
993 
994     /* Switch/Case conversion */
995 
996     Status = AcpiDmProcessSwitch (Op);
997     return (Status);
998 }
999 
1000 
1001 /*******************************************************************************
1002  *
1003  * FUNCTION:    AcpiDmProcessResourceDescriptors
1004  *
1005  * PARAMETERS:  ASL_WALK_CALLBACK
1006  *
1007  * RETURN:      ACPI_STATUS
1008  *
1009  * DESCRIPTION: Convert fixed-offset references to resource descriptors to
1010  *              symbolic references. Should only be called after namespace has
1011  *              been cross referenced.
1012  *
1013  ******************************************************************************/
1014 
1015 static ACPI_STATUS
AcpiDmProcessResourceDescriptors(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)1016 AcpiDmProcessResourceDescriptors (
1017     ACPI_PARSE_OBJECT       *Op,
1018     UINT32                  Level,
1019     void                    *Context)
1020 {
1021     ACPI_OP_WALK_INFO       *Info = Context;
1022     const ACPI_OPCODE_INFO  *OpInfo;
1023     ACPI_WALK_STATE         *WalkState;
1024     ACPI_OBJECT_TYPE        ObjectType;
1025     ACPI_STATUS             Status;
1026 
1027 
1028     WalkState = Info->WalkState;
1029     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
1030 
1031     /* Open new scope if necessary */
1032 
1033     ObjectType = OpInfo->ObjectType;
1034     if (AcpiNsOpensScope (ObjectType))
1035     {
1036         if (Op->Common.Node)
1037         {
1038 
1039             Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType,
1040                 WalkState);
1041             if (ACPI_FAILURE (Status))
1042             {
1043                 return (Status);
1044             }
1045         }
1046     }
1047 
1048     /*
1049      * Check if this operator contains a reference to a resource descriptor.
1050      * If so, convert the reference into a symbolic reference.
1051      */
1052     AcpiDmCheckResourceReference (Op, WalkState);
1053     return (AE_OK);
1054 }
1055 
1056 /*******************************************************************************
1057  *
1058  * FUNCTION:    AcpiDmCommonAscendingOp
1059  *
1060  * PARAMETERS:  ASL_WALK_CALLBACK
1061  *
1062  * RETURN:      None
1063  *
1064  * DESCRIPTION: Ascending handler for combined parse/namespace walks. Closes
1065  *              scope if necessary.
1066  *
1067  ******************************************************************************/
1068 
1069 static ACPI_STATUS
AcpiDmCommonAscendingOp(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)1070 AcpiDmCommonAscendingOp (
1071     ACPI_PARSE_OBJECT       *Op,
1072     UINT32                  Level,
1073     void                    *Context)
1074 {
1075     ACPI_OP_WALK_INFO       *Info = Context;
1076     ACPI_OBJECT_TYPE        ObjectType;
1077 
1078 
1079     /* Close scope if necessary */
1080 
1081     ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
1082 
1083     if (AcpiNsOpensScope (ObjectType))
1084     {
1085         (void) AcpiDsScopeStackPop (Info->WalkState);
1086     }
1087 
1088     return (AE_OK);
1089 }
1090 
1091 /*******************************************************************************
1092  *
1093  * FUNCTION:    AcpiDmInspectPossibleArgs
1094  *
1095  * PARAMETERS:  CurrentOpArgCount   - Which arg of the current op was the
1096  *                                    possible method invocation found
1097  *              TargetCount         - Number of targets (0,1,2) for this op
1098  *              Op                  - Parse op
1099  *
1100  * RETURN:      Status
1101  *
1102  * DESCRIPTION: Examine following args and next ops for possible arguments
1103  *              for an unrecognized method invocation.
1104  *
1105  ******************************************************************************/
1106 
1107 static UINT32
AcpiDmInspectPossibleArgs(UINT32 CurrentOpArgCount,UINT32 TargetCount,ACPI_PARSE_OBJECT * Op)1108 AcpiDmInspectPossibleArgs (
1109     UINT32                  CurrentOpArgCount,
1110     UINT32                  TargetCount,
1111     ACPI_PARSE_OBJECT       *Op)
1112 {
1113     const ACPI_OPCODE_INFO  *OpInfo;
1114     UINT32                  i;
1115     UINT32                  ArgumentCount = 0;
1116     ACPI_PARSE_OBJECT       *NextOp;
1117     ACPI_PARSE_OBJECT       *ExecuteOp;
1118 
1119 
1120     if (!Op)
1121     {
1122         return (0);
1123     }
1124 
1125     /* Lookahead for the maximum number of possible arguments */
1126 
1127     NextOp = Op->Common.Next;
1128 
1129     for (i = 0; (i < ACPI_METHOD_NUM_ARGS) && NextOp; i++)
1130     {
1131         OpInfo = AcpiPsGetOpcodeInfo (NextOp->Common.AmlOpcode);
1132 
1133         /* Any one of these operators is "very probably" not a method arg */
1134 
1135         if ((NextOp->Common.AmlOpcode == AML_STORE_OP) ||
1136             (NextOp->Common.AmlOpcode == AML_NOTIFY_OP) ||
1137             (OpInfo->Class == AML_CLASS_CONTROL) ||
1138             (OpInfo->Class == AML_CLASS_CREATE) ||
1139             (OpInfo->Class == AML_CLASS_NAMED_OBJECT))
1140         {
1141             break;
1142         }
1143 
1144         if (OpInfo->Class == AML_CLASS_EXECUTE)
1145         {
1146             /* Probable that this is method arg if there is no target */
1147 
1148             ExecuteOp = NextOp->Common.Value.Arg;
1149             while (ExecuteOp)
1150             {
1151                 if ((ExecuteOp->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
1152                     (ExecuteOp->Common.Value.Arg == NULL))
1153                 {
1154                     /* No target, could be a method arg */
1155 
1156                     break;
1157                 }
1158 
1159                 if (NextOp->Common.AmlOpcode == AML_REF_OF_OP)
1160                 {
1161                     break;
1162                 }
1163 
1164                 ExecuteOp = ExecuteOp->Common.Next;
1165             }
1166 
1167             if (!ExecuteOp)
1168             {
1169                 /* Has a target, not method arg */
1170 
1171                 return (ArgumentCount);
1172             }
1173         }
1174 
1175         ArgumentCount++;
1176         NextOp = NextOp->Common.Next;
1177     }
1178 
1179     return (ArgumentCount);
1180 }
1181