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