Branch data Line data Source code
1 : : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 : : /******************************************************************************
3 : : *
4 : : * Module Name: dsargs - Support for execution of dynamic arguments for static
5 : : * objects (regions, fields, buffer fields, etc.)
6 : : *
7 : : * Copyright (C) 2000 - 2020, Intel Corp.
8 : : *
9 : : *****************************************************************************/
10 : :
11 : : #include <acpi/acpi.h>
12 : : #include "accommon.h"
13 : : #include "acparser.h"
14 : : #include "amlcode.h"
15 : : #include "acdispat.h"
16 : : #include "acnamesp.h"
17 : :
18 : : #define _COMPONENT ACPI_DISPATCHER
19 : : ACPI_MODULE_NAME("dsargs")
20 : :
21 : : /* Local prototypes */
22 : : static acpi_status
23 : : acpi_ds_execute_arguments(struct acpi_namespace_node *node,
24 : : struct acpi_namespace_node *scope_node,
25 : : u32 aml_length, u8 *aml_start);
26 : :
27 : : /*******************************************************************************
28 : : *
29 : : * FUNCTION: acpi_ds_execute_arguments
30 : : *
31 : : * PARAMETERS: node - Object NS node
32 : : * scope_node - Parent NS node
33 : : * aml_length - Length of executable AML
34 : : * aml_start - Pointer to the AML
35 : : *
36 : : * RETURN: Status.
37 : : *
38 : : * DESCRIPTION: Late (deferred) execution of region or field arguments
39 : : *
40 : : ******************************************************************************/
41 : :
42 : : static acpi_status
43 : 112 : acpi_ds_execute_arguments(struct acpi_namespace_node *node,
44 : : struct acpi_namespace_node *scope_node,
45 : : u32 aml_length, u8 *aml_start)
46 : : {
47 : 112 : acpi_status status;
48 : 112 : union acpi_parse_object *op;
49 : 112 : struct acpi_walk_state *walk_state;
50 : :
51 : 112 : ACPI_FUNCTION_TRACE_PTR(ds_execute_arguments, aml_start);
52 : :
53 : : /* Allocate a new parser op to be the root of the parsed tree */
54 : :
55 : 112 : op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP, aml_start);
56 [ + - ]: 112 : if (!op) {
57 : : return_ACPI_STATUS(AE_NO_MEMORY);
58 : : }
59 : :
60 : : /* Save the Node for use in acpi_ps_parse_aml */
61 : :
62 : 112 : op->common.node = scope_node;
63 : :
64 : : /* Create and initialize a new parser state */
65 : :
66 : 112 : walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL);
67 [ - + ]: 112 : if (!walk_state) {
68 : 0 : status = AE_NO_MEMORY;
69 : 0 : goto cleanup;
70 : : }
71 : :
72 : 112 : status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start,
73 : : aml_length, NULL, ACPI_IMODE_LOAD_PASS1);
74 [ - + ]: 112 : if (ACPI_FAILURE(status)) {
75 : 0 : acpi_ds_delete_walk_state(walk_state);
76 : 0 : goto cleanup;
77 : : }
78 : :
79 : : /* Mark this parse as a deferred opcode */
80 : :
81 : 112 : walk_state->parse_flags = ACPI_PARSE_DEFERRED_OP;
82 : 112 : walk_state->deferred_node = node;
83 : :
84 : : /* Pass1: Parse the entire declaration */
85 : :
86 : 112 : status = acpi_ps_parse_aml(walk_state);
87 [ - + ]: 112 : if (ACPI_FAILURE(status)) {
88 : 0 : goto cleanup;
89 : : }
90 : :
91 : : /* Get and init the Op created above */
92 : :
93 : 112 : op->common.node = node;
94 : 112 : acpi_ps_delete_parse_tree(op);
95 : :
96 : : /* Evaluate the deferred arguments */
97 : :
98 : 112 : op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP, aml_start);
99 [ + - ]: 112 : if (!op) {
100 : : return_ACPI_STATUS(AE_NO_MEMORY);
101 : : }
102 : :
103 : 112 : op->common.node = scope_node;
104 : :
105 : : /* Create and initialize a new parser state */
106 : :
107 : 112 : walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL);
108 [ - + ]: 112 : if (!walk_state) {
109 : 0 : status = AE_NO_MEMORY;
110 : 0 : goto cleanup;
111 : : }
112 : :
113 : : /* Execute the opcode and arguments */
114 : :
115 : 112 : status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start,
116 : : aml_length, NULL, ACPI_IMODE_EXECUTE);
117 [ - + ]: 112 : if (ACPI_FAILURE(status)) {
118 : 0 : acpi_ds_delete_walk_state(walk_state);
119 : 0 : goto cleanup;
120 : : }
121 : :
122 : : /* Mark this execution as a deferred opcode */
123 : :
124 : 112 : walk_state->deferred_node = node;
125 : 112 : status = acpi_ps_parse_aml(walk_state);
126 : :
127 : 112 : cleanup:
128 : 112 : acpi_ps_delete_parse_tree(op);
129 : 112 : return_ACPI_STATUS(status);
130 : : }
131 : :
132 : : /*******************************************************************************
133 : : *
134 : : * FUNCTION: acpi_ds_get_buffer_field_arguments
135 : : *
136 : : * PARAMETERS: obj_desc - A valid buffer_field object
137 : : *
138 : : * RETURN: Status.
139 : : *
140 : : * DESCRIPTION: Get buffer_field Buffer and Index. This implements the late
141 : : * evaluation of these field attributes.
142 : : *
143 : : ******************************************************************************/
144 : :
145 : : acpi_status
146 : 0 : acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc)
147 : : {
148 : 0 : union acpi_operand_object *extra_desc;
149 : 0 : struct acpi_namespace_node *node;
150 : 0 : acpi_status status;
151 : :
152 : 0 : ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_field_arguments, obj_desc);
153 : :
154 [ # # ]: 0 : if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
155 : : return_ACPI_STATUS(AE_OK);
156 : : }
157 : :
158 : : /* Get the AML pointer (method object) and buffer_field node */
159 : :
160 : 0 : extra_desc = acpi_ns_get_secondary_object(obj_desc);
161 : 0 : node = obj_desc->buffer_field.node;
162 : :
163 : : ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
164 : 0 : (ACPI_TYPE_BUFFER_FIELD, node, NULL));
165 : :
166 : : ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n",
167 : 0 : acpi_ut_get_node_name(node)));
168 : :
169 : : /* Execute the AML code for the term_arg arguments */
170 : :
171 : 0 : status = acpi_ds_execute_arguments(node, node->parent,
172 : : extra_desc->extra.aml_length,
173 : : extra_desc->extra.aml_start);
174 : 0 : return_ACPI_STATUS(status);
175 : : }
176 : :
177 : : /*******************************************************************************
178 : : *
179 : : * FUNCTION: acpi_ds_get_bank_field_arguments
180 : : *
181 : : * PARAMETERS: obj_desc - A valid bank_field object
182 : : *
183 : : * RETURN: Status.
184 : : *
185 : : * DESCRIPTION: Get bank_field bank_value. This implements the late
186 : : * evaluation of these field attributes.
187 : : *
188 : : ******************************************************************************/
189 : :
190 : : acpi_status
191 : 0 : acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc)
192 : : {
193 : 0 : union acpi_operand_object *extra_desc;
194 : 0 : struct acpi_namespace_node *node;
195 : 0 : acpi_status status;
196 : :
197 : 0 : ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc);
198 : :
199 [ # # ]: 0 : if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
200 : : return_ACPI_STATUS(AE_OK);
201 : : }
202 : :
203 : : /* Get the AML pointer (method object) and bank_field node */
204 : :
205 : 0 : extra_desc = acpi_ns_get_secondary_object(obj_desc);
206 : 0 : node = obj_desc->bank_field.node;
207 : :
208 : : ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
209 : 0 : (ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL));
210 : :
211 : : ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n",
212 : 0 : acpi_ut_get_node_name(node)));
213 : :
214 : : /* Execute the AML code for the term_arg arguments */
215 : :
216 : 0 : status = acpi_ds_execute_arguments(node, node->parent,
217 : : extra_desc->extra.aml_length,
218 : : extra_desc->extra.aml_start);
219 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
220 : : return_ACPI_STATUS(status);
221 : : }
222 : :
223 : 0 : status = acpi_ut_add_address_range(obj_desc->region.space_id,
224 : : obj_desc->region.address,
225 : : obj_desc->region.length, node);
226 : 0 : return_ACPI_STATUS(status);
227 : : }
228 : :
229 : : /*******************************************************************************
230 : : *
231 : : * FUNCTION: acpi_ds_get_buffer_arguments
232 : : *
233 : : * PARAMETERS: obj_desc - A valid Buffer object
234 : : *
235 : : * RETURN: Status.
236 : : *
237 : : * DESCRIPTION: Get Buffer length and initializer byte list. This implements
238 : : * the late evaluation of these attributes.
239 : : *
240 : : ******************************************************************************/
241 : :
242 : 1988 : acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc)
243 : : {
244 : 1988 : struct acpi_namespace_node *node;
245 : 1988 : acpi_status status;
246 : :
247 : 1988 : ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc);
248 : :
249 [ - + ]: 1988 : if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
250 : : return_ACPI_STATUS(AE_OK);
251 : : }
252 : :
253 : : /* Get the Buffer node */
254 : :
255 : 0 : node = obj_desc->buffer.node;
256 [ # # ]: 0 : if (!node) {
257 : 0 : ACPI_ERROR((AE_INFO,
258 : : "No pointer back to namespace node in buffer object %p",
259 : : obj_desc));
260 : 0 : return_ACPI_STATUS(AE_AML_INTERNAL);
261 : : }
262 : :
263 : 0 : ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Buffer Arg Init\n"));
264 : :
265 : : /* Execute the AML code for the term_arg arguments */
266 : :
267 : 0 : status = acpi_ds_execute_arguments(node, node,
268 : : obj_desc->buffer.aml_length,
269 : : obj_desc->buffer.aml_start);
270 : 0 : return_ACPI_STATUS(status);
271 : : }
272 : :
273 : : /*******************************************************************************
274 : : *
275 : : * FUNCTION: acpi_ds_get_package_arguments
276 : : *
277 : : * PARAMETERS: obj_desc - A valid Package object
278 : : *
279 : : * RETURN: Status.
280 : : *
281 : : * DESCRIPTION: Get Package length and initializer byte list. This implements
282 : : * the late evaluation of these attributes.
283 : : *
284 : : ******************************************************************************/
285 : :
286 : 4195 : acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc)
287 : : {
288 : 4195 : struct acpi_namespace_node *node;
289 : 4195 : acpi_status status;
290 : :
291 : 4195 : ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc);
292 : :
293 [ + + ]: 4195 : if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
294 : : return_ACPI_STATUS(AE_OK);
295 : : }
296 : :
297 : : /* Get the Package node */
298 : :
299 : 112 : node = obj_desc->package.node;
300 [ - + ]: 112 : if (!node) {
301 : 0 : ACPI_ERROR((AE_INFO,
302 : : "No pointer back to namespace node in package %p",
303 : : obj_desc));
304 : 0 : return_ACPI_STATUS(AE_AML_INTERNAL);
305 : : }
306 : :
307 : : ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Package Argument Init, AML Ptr: %p\n",
308 : 112 : obj_desc->package.aml_start));
309 : :
310 : : /* Execute the AML code for the term_arg arguments */
311 : :
312 : 112 : status = acpi_ds_execute_arguments(node, node,
313 : : obj_desc->package.aml_length,
314 : : obj_desc->package.aml_start);
315 : :
316 : 112 : return_ACPI_STATUS(status);
317 : : }
318 : :
319 : : /*******************************************************************************
320 : : *
321 : : * FUNCTION: acpi_ds_get_region_arguments
322 : : *
323 : : * PARAMETERS: obj_desc - A valid region object
324 : : *
325 : : * RETURN: Status.
326 : : *
327 : : * DESCRIPTION: Get region address and length. This implements the late
328 : : * evaluation of these region attributes.
329 : : *
330 : : ******************************************************************************/
331 : :
332 : 0 : acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)
333 : : {
334 : 0 : struct acpi_namespace_node *node;
335 : 0 : acpi_status status;
336 : 0 : union acpi_operand_object *extra_desc;
337 : :
338 : 0 : ACPI_FUNCTION_TRACE_PTR(ds_get_region_arguments, obj_desc);
339 : :
340 [ # # ]: 0 : if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
341 : : return_ACPI_STATUS(AE_OK);
342 : : }
343 : :
344 : 0 : extra_desc = acpi_ns_get_secondary_object(obj_desc);
345 [ # # ]: 0 : if (!extra_desc) {
346 : : return_ACPI_STATUS(AE_NOT_EXIST);
347 : : }
348 : :
349 : : /* Get the Region node */
350 : :
351 : 0 : node = obj_desc->region.node;
352 : :
353 : : ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
354 : 0 : (ACPI_TYPE_REGION, node, NULL));
355 : :
356 : : ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
357 : : "[%4.4s] OpRegion Arg Init at AML %p\n",
358 : : acpi_ut_get_node_name(node),
359 : 0 : extra_desc->extra.aml_start));
360 : :
361 : : /* Execute the argument AML */
362 : :
363 : 0 : status = acpi_ds_execute_arguments(node, extra_desc->extra.scope_node,
364 : : extra_desc->extra.aml_length,
365 : : extra_desc->extra.aml_start);
366 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
367 : : return_ACPI_STATUS(status);
368 : : }
369 : :
370 : 0 : status = acpi_ut_add_address_range(obj_desc->region.space_id,
371 : : obj_desc->region.address,
372 : : obj_desc->region.length, node);
373 : 0 : return_ACPI_STATUS(status);
374 : : }
|