xref: /linux/drivers/acpi/acpica/psscope.c (revision afca12e35e711ae8f97e835a3704cc305592eac9)
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
3  *
4  * Module Name: psscope - Parser scope stack management routines
5  *
6  * Copyright (C) 2000 - 2023, Intel Corp.
7  *
8  *****************************************************************************/
9 
10 #include <acpi/acpi.h>
11 #include "accommon.h"
12 #include "acparser.h"
13 
14 #define _COMPONENT          ACPI_PARSER
15 ACPI_MODULE_NAME("psscope")
16 
17 /*******************************************************************************
18  *
19  * FUNCTION:    acpi_ps_get_parent_scope
20  *
21  * PARAMETERS:  parser_state        - Current parser state object
22  *
23  * RETURN:      Pointer to an Op object
24  *
25  * DESCRIPTION: Get parent of current op being parsed
26  *
27  ******************************************************************************/
28 union acpi_parse_object *acpi_ps_get_parent_scope(struct acpi_parse_state
29 						  *parser_state)
30 {
31 
32 	return (parser_state->scope->parse_scope.op);
33 }
34 
35 /*******************************************************************************
36  *
37  * FUNCTION:    acpi_ps_has_completed_scope
38  *
39  * PARAMETERS:  parser_state        - Current parser state object
40  *
41  * RETURN:      Boolean, TRUE = scope completed.
42  *
43  * DESCRIPTION: Is parsing of current argument complete?  Determined by
44  *              1) AML pointer is at or beyond the end of the scope
45  *              2) The scope argument count has reached zero.
46  *
47  ******************************************************************************/
48 
49 u8 acpi_ps_has_completed_scope(struct acpi_parse_state * parser_state)
50 {
51 
52 	return ((u8)
53 		((parser_state->aml >= parser_state->scope->parse_scope.arg_end
54 		  || !parser_state->scope->parse_scope.arg_count)));
55 }
56 
57 /*******************************************************************************
58  *
59  * FUNCTION:    acpi_ps_init_scope
60  *
61  * PARAMETERS:  parser_state        - Current parser state object
62  *              root                - the Root Node of this new scope
63  *
64  * RETURN:      Status
65  *
66  * DESCRIPTION: Allocate and init a new scope object
67  *
68  ******************************************************************************/
69 
70 acpi_status
71 acpi_ps_init_scope(struct acpi_parse_state * parser_state,
72 		   union acpi_parse_object * root_op)
73 {
74 	union acpi_generic_state *scope;
75 
76 	ACPI_FUNCTION_TRACE_PTR(ps_init_scope, root_op);
77 
78 	scope = acpi_ut_create_generic_state();
79 	if (!scope) {
80 		return_ACPI_STATUS(AE_NO_MEMORY);
81 	}
82 
83 	scope->common.descriptor_type = ACPI_DESC_TYPE_STATE_RPSCOPE;
84 	scope->parse_scope.op = root_op;
85 	scope->parse_scope.arg_count = ACPI_VAR_ARGS;
86 	scope->parse_scope.arg_end = parser_state->aml_end;
87 	scope->parse_scope.pkg_end = parser_state->aml_end;
88 
89 	parser_state->scope = scope;
90 	parser_state->start_op = root_op;
91 
92 	return_ACPI_STATUS(AE_OK);
93 }
94 
95 /*******************************************************************************
96  *
97  * FUNCTION:    acpi_ps_push_scope
98  *
99  * PARAMETERS:  parser_state        - Current parser state object
100  *              op                  - Current op to be pushed
101  *              remaining_args      - List of args remaining
102  *              arg_count           - Fixed or variable number of args
103  *
104  * RETURN:      Status
105  *
106  * DESCRIPTION: Push current op to begin parsing its argument
107  *
108  ******************************************************************************/
109 
110 acpi_status
111 acpi_ps_push_scope(struct acpi_parse_state *parser_state,
112 		   union acpi_parse_object *op,
113 		   u32 remaining_args, u32 arg_count)
114 {
115 	union acpi_generic_state *scope;
116 
117 	ACPI_FUNCTION_TRACE_PTR(ps_push_scope, op);
118 
119 	scope = acpi_ut_create_generic_state();
120 	if (!scope) {
121 		return_ACPI_STATUS(AE_NO_MEMORY);
122 	}
123 
124 	scope->common.descriptor_type = ACPI_DESC_TYPE_STATE_PSCOPE;
125 	scope->parse_scope.op = op;
126 	scope->parse_scope.arg_list = remaining_args;
127 	scope->parse_scope.arg_count = arg_count;
128 	scope->parse_scope.pkg_end = parser_state->pkg_end;
129 
130 	/* Push onto scope stack */
131 
132 	acpi_ut_push_generic_state(&parser_state->scope, scope);
133 
134 	if (arg_count == ACPI_VAR_ARGS) {
135 
136 		/* Multiple arguments */
137 
138 		scope->parse_scope.arg_end = parser_state->pkg_end;
139 	} else {
140 		/* Single argument */
141 
142 		scope->parse_scope.arg_end = ACPI_TO_POINTER(ACPI_MAX_PTR);
143 	}
144 
145 	return_ACPI_STATUS(AE_OK);
146 }
147 
148 /*******************************************************************************
149  *
150  * FUNCTION:    acpi_ps_pop_scope
151  *
152  * PARAMETERS:  parser_state        - Current parser state object
153  *              op                  - Where the popped op is returned
154  *              arg_list            - Where the popped "next argument" is
155  *                                    returned
156  *              arg_count           - Count of objects in arg_list
157  *
158  * RETURN:      Status
159  *
160  * DESCRIPTION: Return to parsing a previous op
161  *
162  ******************************************************************************/
163 
164 void
165 acpi_ps_pop_scope(struct acpi_parse_state *parser_state,
166 		  union acpi_parse_object **op, u32 * arg_list, u32 * arg_count)
167 {
168 	union acpi_generic_state *scope = parser_state->scope;
169 
170 	ACPI_FUNCTION_TRACE(ps_pop_scope);
171 
172 	/* Only pop the scope if there is in fact a next scope */
173 
174 	if (scope->common.next) {
175 		scope = acpi_ut_pop_generic_state(&parser_state->scope);
176 
177 		/* Return to parsing previous op */
178 
179 		*op = scope->parse_scope.op;
180 		*arg_list = scope->parse_scope.arg_list;
181 		*arg_count = scope->parse_scope.arg_count;
182 		parser_state->pkg_end = scope->parse_scope.pkg_end;
183 
184 		/* All done with this scope state structure */
185 
186 		acpi_ut_delete_generic_state(scope);
187 	} else {
188 		/* Empty parse stack, prepare to fetch next opcode */
189 
190 		*op = NULL;
191 		*arg_list = 0;
192 		*arg_count = 0;
193 	}
194 
195 	ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
196 			  "Popped Op %p Args %X\n", *op, *arg_count));
197 	return_VOID;
198 }
199 
200 /*******************************************************************************
201  *
202  * FUNCTION:    acpi_ps_cleanup_scope
203  *
204  * PARAMETERS:  parser_state        - Current parser state object
205  *
206  * RETURN:      None
207  *
208  * DESCRIPTION: Destroy available list, remaining stack levels, and return
209  *              root scope
210  *
211  ******************************************************************************/
212 
213 void acpi_ps_cleanup_scope(struct acpi_parse_state *parser_state)
214 {
215 	union acpi_generic_state *scope;
216 
217 	ACPI_FUNCTION_TRACE_PTR(ps_cleanup_scope, parser_state);
218 
219 	if (!parser_state) {
220 		return_VOID;
221 	}
222 
223 	/* Delete anything on the scope stack */
224 
225 	while (parser_state->scope) {
226 		scope = acpi_ut_pop_generic_state(&parser_state->scope);
227 		acpi_ut_delete_generic_state(scope);
228 	}
229 
230 	return_VOID;
231 }
232