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
15ACPI_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 ******************************************************************************/
28union 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
49u8 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
70acpi_status
71acpi_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
110acpi_status
111acpi_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
164void
165acpi_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
213void 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