Linux-libre 4.19.123-gnu
[librecmc/linux-libre.git] / drivers / acpi / acpica / dsargs.c
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 - 2018, 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 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
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
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
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
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
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 }