xref: /reactos/drivers/bus/acpi/acpica/parser/pstree.c (revision 03b24380)
1 /******************************************************************************
2  *
3  * Module Name: pstree - Parser op tree manipulation/traversal/search
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 "acconvert.h"
49 
50 #define _COMPONENT          ACPI_PARSER
51         ACPI_MODULE_NAME    ("pstree")
52 
53 /* Local prototypes */
54 
55 #ifdef ACPI_OBSOLETE_FUNCTIONS
56 ACPI_PARSE_OBJECT *
57 AcpiPsGetChild (
58     ACPI_PARSE_OBJECT       *op);
59 #endif
60 
61 
62 /*******************************************************************************
63  *
64  * FUNCTION:    AcpiPsGetArg
65  *
66  * PARAMETERS:  Op              - Get an argument for this op
67  *              Argn            - Nth argument to get
68  *
69  * RETURN:      The argument (as an Op object). NULL if argument does not exist
70  *
71  * DESCRIPTION: Get the specified op's argument.
72  *
73  ******************************************************************************/
74 
75 ACPI_PARSE_OBJECT *
AcpiPsGetArg(ACPI_PARSE_OBJECT * Op,UINT32 Argn)76 AcpiPsGetArg (
77     ACPI_PARSE_OBJECT       *Op,
78     UINT32                  Argn)
79 {
80     ACPI_PARSE_OBJECT       *Arg = NULL;
81     const ACPI_OPCODE_INFO  *OpInfo;
82 
83 
84     ACPI_FUNCTION_ENTRY ();
85 
86 /*
87     if (Op->Common.AmlOpcode == AML_INT_CONNECTION_OP)
88     {
89         return (Op->Common.Value.Arg);
90     }
91 */
92     /* Get the info structure for this opcode */
93 
94     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
95     if (OpInfo->Class == AML_CLASS_UNKNOWN)
96     {
97         /* Invalid opcode or ASCII character */
98 
99         return (NULL);
100     }
101 
102     /* Check if this opcode requires argument sub-objects */
103 
104     if (!(OpInfo->Flags & AML_HAS_ARGS))
105     {
106         /* Has no linked argument objects */
107 
108         return (NULL);
109     }
110 
111     /* Get the requested argument object */
112 
113     Arg = Op->Common.Value.Arg;
114     while (Arg && Argn)
115     {
116         Argn--;
117         Arg = Arg->Common.Next;
118     }
119 
120     return (Arg);
121 }
122 
123 
124 /*******************************************************************************
125  *
126  * FUNCTION:    AcpiPsAppendArg
127  *
128  * PARAMETERS:  Op              - Append an argument to this Op.
129  *              Arg             - Argument Op to append
130  *
131  * RETURN:      None.
132  *
133  * DESCRIPTION: Append an argument to an op's argument list (a NULL arg is OK)
134  *
135  ******************************************************************************/
136 
137 void
AcpiPsAppendArg(ACPI_PARSE_OBJECT * Op,ACPI_PARSE_OBJECT * Arg)138 AcpiPsAppendArg (
139     ACPI_PARSE_OBJECT       *Op,
140     ACPI_PARSE_OBJECT       *Arg)
141 {
142     ACPI_PARSE_OBJECT       *PrevArg;
143     const ACPI_OPCODE_INFO  *OpInfo;
144 
145 
146     ACPI_FUNCTION_TRACE (PsAppendArg);
147 
148 
149     if (!Op)
150     {
151         return_VOID;
152     }
153 
154     /* Get the info structure for this opcode */
155 
156     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
157     if (OpInfo->Class == AML_CLASS_UNKNOWN)
158     {
159         /* Invalid opcode */
160 
161         ACPI_ERROR ((AE_INFO, "Invalid AML Opcode: 0x%2.2X",
162             Op->Common.AmlOpcode));
163         return_VOID;
164     }
165 
166     /* Check if this opcode requires argument sub-objects */
167 
168     if (!(OpInfo->Flags & AML_HAS_ARGS))
169     {
170         /* Has no linked argument objects */
171 
172         return_VOID;
173     }
174 
175     /* Append the argument to the linked argument list */
176 
177     if (Op->Common.Value.Arg)
178     {
179         /* Append to existing argument list */
180 
181         PrevArg = Op->Common.Value.Arg;
182         while (PrevArg->Common.Next)
183         {
184             PrevArg = PrevArg->Common.Next;
185         }
186         PrevArg->Common.Next = Arg;
187     }
188     else
189     {
190         /* No argument list, this will be the first argument */
191 
192         Op->Common.Value.Arg = Arg;
193     }
194 
195     /* Set the parent in this arg and any args linked after it */
196 
197     while (Arg)
198     {
199         Arg->Common.Parent = Op;
200         Arg = Arg->Common.Next;
201 
202         Op->Common.ArgListLength++;
203     }
204 
205     return_VOID;
206 }
207 
208 
209 /*******************************************************************************
210  *
211  * FUNCTION:    AcpiPsGetDepthNext
212  *
213  * PARAMETERS:  Origin          - Root of subtree to search
214  *              Op              - Last (previous) Op that was found
215  *
216  * RETURN:      Next Op found in the search.
217  *
218  * DESCRIPTION: Get next op in tree (walking the tree in depth-first order)
219  *              Return NULL when reaching "origin" or when walking up from root
220  *
221  ******************************************************************************/
222 
223 ACPI_PARSE_OBJECT *
AcpiPsGetDepthNext(ACPI_PARSE_OBJECT * Origin,ACPI_PARSE_OBJECT * Op)224 AcpiPsGetDepthNext (
225     ACPI_PARSE_OBJECT       *Origin,
226     ACPI_PARSE_OBJECT       *Op)
227 {
228     ACPI_PARSE_OBJECT       *Next = NULL;
229     ACPI_PARSE_OBJECT       *Parent;
230     ACPI_PARSE_OBJECT       *Arg;
231 
232 
233     ACPI_FUNCTION_ENTRY ();
234 
235 
236     if (!Op)
237     {
238         return (NULL);
239     }
240 
241     /* Look for an argument or child */
242 
243     Next = AcpiPsGetArg (Op, 0);
244     if (Next)
245     {
246         ASL_CV_LABEL_FILENODE (Next);
247         return (Next);
248     }
249 
250     /* Look for a sibling */
251 
252     Next = Op->Common.Next;
253     if (Next)
254     {
255         ASL_CV_LABEL_FILENODE (Next);
256         return (Next);
257     }
258 
259     /* Look for a sibling of parent */
260 
261     Parent = Op->Common.Parent;
262 
263     while (Parent)
264     {
265         Arg = AcpiPsGetArg (Parent, 0);
266         while (Arg && (Arg != Origin) && (Arg != Op))
267         {
268 
269             ASL_CV_LABEL_FILENODE (Arg);
270             Arg = Arg->Common.Next;
271         }
272 
273         if (Arg == Origin)
274         {
275             /* Reached parent of origin, end search */
276 
277             return (NULL);
278         }
279 
280         if (Parent->Common.Next)
281         {
282             /* Found sibling of parent */
283 
284             ASL_CV_LABEL_FILENODE (Parent->Common.Next);
285             return (Parent->Common.Next);
286         }
287 
288         Op = Parent;
289         Parent = Parent->Common.Parent;
290     }
291 
292     ASL_CV_LABEL_FILENODE (Next);
293     return (Next);
294 }
295 
296 
297 #ifdef ACPI_OBSOLETE_FUNCTIONS
298 /*******************************************************************************
299  *
300  * FUNCTION:    AcpiPsGetChild
301  *
302  * PARAMETERS:  Op              - Get the child of this Op
303  *
304  * RETURN:      Child Op, Null if none is found.
305  *
306  * DESCRIPTION: Get op's children or NULL if none
307  *
308  ******************************************************************************/
309 
310 ACPI_PARSE_OBJECT *
AcpiPsGetChild(ACPI_PARSE_OBJECT * Op)311 AcpiPsGetChild (
312     ACPI_PARSE_OBJECT       *Op)
313 {
314     ACPI_PARSE_OBJECT       *Child = NULL;
315 
316 
317     ACPI_FUNCTION_ENTRY ();
318 
319 
320     switch (Op->Common.AmlOpcode)
321     {
322     case AML_SCOPE_OP:
323     case AML_ELSE_OP:
324     case AML_DEVICE_OP:
325     case AML_THERMAL_ZONE_OP:
326     case AML_INT_METHODCALL_OP:
327 
328         Child = AcpiPsGetArg (Op, 0);
329         break;
330 
331     case AML_BUFFER_OP:
332     case AML_PACKAGE_OP:
333     case AML_VARIABLE_PACKAGE_OP:
334     case AML_METHOD_OP:
335     case AML_IF_OP:
336     case AML_WHILE_OP:
337     case AML_FIELD_OP:
338 
339         Child = AcpiPsGetArg (Op, 1);
340         break;
341 
342     case AML_POWER_RESOURCE_OP:
343     case AML_INDEX_FIELD_OP:
344 
345         Child = AcpiPsGetArg (Op, 2);
346         break;
347 
348     case AML_PROCESSOR_OP:
349     case AML_BANK_FIELD_OP:
350 
351         Child = AcpiPsGetArg (Op, 3);
352         break;
353 
354     default:
355 
356         /* All others have no children */
357 
358         break;
359     }
360 
361     return (Child);
362 }
363 #endif
364