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 - 2022, 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
acpi_ds_execute_arguments(struct acpi_namespace_node * node,struct acpi_namespace_node * scope_node,u32 aml_length,u8 * aml_start)43 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 	acpi_status status;
48 	union acpi_parse_object *op;
49 	struct acpi_walk_state *walk_state;
50 
51 	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 	op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP, aml_start);
56 	if (!op) {
57 		return_ACPI_STATUS(AE_NO_MEMORY);
58 	}
59 
60 	/* Save the Node for use in acpi_ps_parse_aml */
61 
62 	op->common.node = scope_node;
63 
64 	/* Create and initialize a new parser state */
65 
66 	walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL);
67 	if (!walk_state) {
68 		status = AE_NO_MEMORY;
69 		goto cleanup;
70 	}
71 
72 	status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start,
73 				       aml_length, NULL, ACPI_IMODE_LOAD_PASS1);
74 	if (ACPI_FAILURE(status)) {
75 		acpi_ds_delete_walk_state(walk_state);
76 		goto cleanup;
77 	}
78 
79 	/* Mark this parse as a deferred opcode */
80 
81 	walk_state->parse_flags = ACPI_PARSE_DEFERRED_OP;
82 	walk_state->deferred_node = node;
83 
84 	/* Pass1: Parse the entire declaration */
85 
86 	status = acpi_ps_parse_aml(walk_state);
87 	if (ACPI_FAILURE(status)) {
88 		goto cleanup;
89 	}
90 
91 	/* Get and init the Op created above */
92 
93 	op->common.node = node;
94 	acpi_ps_delete_parse_tree(op);
95 
96 	/* Evaluate the deferred arguments */
97 
98 	op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP, aml_start);
99 	if (!op) {
100 		return_ACPI_STATUS(AE_NO_MEMORY);
101 	}
102 
103 	op->common.node = scope_node;
104 
105 	/* Create and initialize a new parser state */
106 
107 	walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL);
108 	if (!walk_state) {
109 		status = AE_NO_MEMORY;
110 		goto cleanup;
111 	}
112 
113 	/* Execute the opcode and arguments */
114 
115 	status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start,
116 				       aml_length, NULL, ACPI_IMODE_EXECUTE);
117 	if (ACPI_FAILURE(status)) {
118 		acpi_ds_delete_walk_state(walk_state);
119 		goto cleanup;
120 	}
121 
122 	/* Mark this execution as a deferred opcode */
123 
124 	walk_state->deferred_node = node;
125 	status = acpi_ps_parse_aml(walk_state);
126 
127 cleanup:
128 	acpi_ps_delete_parse_tree(op);
129 	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
acpi_ds_get_buffer_field_arguments(union acpi_operand_object * obj_desc)146 acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc)
147 {
148 	union acpi_operand_object *extra_desc;
149 	struct acpi_namespace_node *node;
150 	acpi_status status;
151 
152 	ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_field_arguments, obj_desc);
153 
154 	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 	extra_desc = acpi_ns_get_secondary_object(obj_desc);
161 	node = obj_desc->buffer_field.node;
162 
163 	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
164 			(ACPI_TYPE_BUFFER_FIELD, node, NULL));
165 
166 	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n",
167 			  acpi_ut_get_node_name(node)));
168 
169 	/* Execute the AML code for the term_arg arguments */
170 
171 	status = acpi_ds_execute_arguments(node, node->parent,
172 					   extra_desc->extra.aml_length,
173 					   extra_desc->extra.aml_start);
174 	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
acpi_ds_get_bank_field_arguments(union acpi_operand_object * obj_desc)191 acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc)
192 {
193 	union acpi_operand_object *extra_desc;
194 	struct acpi_namespace_node *node;
195 	acpi_status status;
196 
197 	ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc);
198 
199 	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 	extra_desc = acpi_ns_get_secondary_object(obj_desc);
206 	node = obj_desc->bank_field.node;
207 
208 	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
209 			(ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL));
210 
211 	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n",
212 			  acpi_ut_get_node_name(node)));
213 
214 	/* Execute the AML code for the term_arg arguments */
215 
216 	status = acpi_ds_execute_arguments(node, node->parent,
217 					   extra_desc->extra.aml_length,
218 					   extra_desc->extra.aml_start);
219 	if (ACPI_FAILURE(status)) {
220 		return_ACPI_STATUS(status);
221 	}
222 
223 	status = acpi_ut_add_address_range(obj_desc->region.space_id,
224 					   obj_desc->region.address,
225 					   obj_desc->region.length, node);
226 	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 
acpi_ds_get_buffer_arguments(union acpi_operand_object * obj_desc)242 acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc)
243 {
244 	struct acpi_namespace_node *node;
245 	acpi_status status;
246 
247 	ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc);
248 
249 	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
250 		return_ACPI_STATUS(AE_OK);
251 	}
252 
253 	/* Get the Buffer node */
254 
255 	node = obj_desc->buffer.node;
256 	if (!node) {
257 		ACPI_ERROR((AE_INFO,
258 			    "No pointer back to namespace node in buffer object %p",
259 			    obj_desc));
260 		return_ACPI_STATUS(AE_AML_INTERNAL);
261 	}
262 
263 	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Buffer Arg Init\n"));
264 
265 	/* Execute the AML code for the term_arg arguments */
266 
267 	status = acpi_ds_execute_arguments(node, node,
268 					   obj_desc->buffer.aml_length,
269 					   obj_desc->buffer.aml_start);
270 	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 
acpi_ds_get_package_arguments(union acpi_operand_object * obj_desc)286 acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc)
287 {
288 	struct acpi_namespace_node *node;
289 	acpi_status status;
290 
291 	ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc);
292 
293 	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
294 		return_ACPI_STATUS(AE_OK);
295 	}
296 
297 	/* Get the Package node */
298 
299 	node = obj_desc->package.node;
300 	if (!node) {
301 		ACPI_ERROR((AE_INFO,
302 			    "No pointer back to namespace node in package %p",
303 			    obj_desc));
304 		return_ACPI_STATUS(AE_AML_INTERNAL);
305 	}
306 
307 	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Package Argument Init, AML Ptr: %p\n",
308 			  obj_desc->package.aml_start));
309 
310 	/* Execute the AML code for the term_arg arguments */
311 
312 	status = acpi_ds_execute_arguments(node, node,
313 					   obj_desc->package.aml_length,
314 					   obj_desc->package.aml_start);
315 
316 	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 
acpi_ds_get_region_arguments(union acpi_operand_object * obj_desc)332 acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)
333 {
334 	struct acpi_namespace_node *node;
335 	acpi_status status;
336 	union acpi_operand_object *extra_desc;
337 
338 	ACPI_FUNCTION_TRACE_PTR(ds_get_region_arguments, obj_desc);
339 
340 	if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
341 		return_ACPI_STATUS(AE_OK);
342 	}
343 
344 	extra_desc = acpi_ns_get_secondary_object(obj_desc);
345 	if (!extra_desc) {
346 		return_ACPI_STATUS(AE_NOT_EXIST);
347 	}
348 
349 	/* Get the Region node */
350 
351 	node = obj_desc->region.node;
352 
353 	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
354 			(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 			  extra_desc->extra.aml_start));
360 
361 	/* Execute the argument AML */
362 
363 	status = acpi_ds_execute_arguments(node, extra_desc->extra.scope_node,
364 					   extra_desc->extra.aml_length,
365 					   extra_desc->extra.aml_start);
366 	if (ACPI_FAILURE(status)) {
367 		return_ACPI_STATUS(status);
368 	}
369 
370 	status = acpi_ut_add_address_range(obj_desc->region.space_id,
371 					   obj_desc->region.address,
372 					   obj_desc->region.length, node);
373 	return_ACPI_STATUS(status);
374 }
375