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 - 2022, 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 ******************************************************************************/
acpi_ps_get_parent_scope(struct acpi_parse_state * parser_state)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
acpi_ps_has_completed_scope(struct acpi_parse_state * parser_state)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
acpi_ps_init_scope(struct acpi_parse_state * parser_state,union acpi_parse_object * root_op)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
acpi_ps_push_scope(struct acpi_parse_state * parser_state,union acpi_parse_object * op,u32 remaining_args,u32 arg_count)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
acpi_ps_pop_scope(struct acpi_parse_state * parser_state,union acpi_parse_object ** op,u32 * arg_list,u32 * arg_count)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
acpi_ps_cleanup_scope(struct acpi_parse_state * parser_state)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