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(list_head: &parser_state->scope, state: 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(list_head: &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(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(list_head: &parser_state->scope); |
227 | acpi_ut_delete_generic_state(state: scope); |
228 | } |
229 | |
230 | return_VOID; |
231 | } |
232 | |