Branch data Line data Source code
1 : : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 : : /******************************************************************************
3 : : *
4 : : * Module Name: psxface - Parser external interfaces
5 : : *
6 : : * Copyright (C) 2000 - 2020, Intel Corp.
7 : : *
8 : : *****************************************************************************/
9 : :
10 : : #include <acpi/acpi.h>
11 : : #include "accommon.h"
12 : : #include "acparser.h"
13 : : #include "acdispat.h"
14 : : #include "acinterp.h"
15 : : #include "actables.h"
16 : : #include "acnamesp.h"
17 : :
18 : : #define _COMPONENT ACPI_PARSER
19 : : ACPI_MODULE_NAME("psxface")
20 : :
21 : : /* Local Prototypes */
22 : : static void
23 : : acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action);
24 : :
25 : : /*******************************************************************************
26 : : *
27 : : * FUNCTION: acpi_debug_trace
28 : : *
29 : : * PARAMETERS: method_name - Valid ACPI name string
30 : : * debug_level - Optional level mask. 0 to use default
31 : : * debug_layer - Optional layer mask. 0 to use default
32 : : * flags - bit 1: one shot(1) or persistent(0)
33 : : *
34 : : * RETURN: Status
35 : : *
36 : : * DESCRIPTION: External interface to enable debug tracing during control
37 : : * method execution
38 : : *
39 : : ******************************************************************************/
40 : :
41 : : acpi_status
42 : 0 : acpi_debug_trace(const char *name, u32 debug_level, u32 debug_layer, u32 flags)
43 : : {
44 : 0 : acpi_status status;
45 : :
46 : 0 : status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
47 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
48 : : return (status);
49 : : }
50 : :
51 : 0 : acpi_gbl_trace_method_name = name;
52 : 0 : acpi_gbl_trace_flags = flags;
53 : 0 : acpi_gbl_trace_dbg_level = debug_level;
54 : 0 : acpi_gbl_trace_dbg_layer = debug_layer;
55 : 0 : status = AE_OK;
56 : :
57 : 0 : (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
58 : 0 : return (status);
59 : : }
60 : :
61 : : /*******************************************************************************
62 : : *
63 : : * FUNCTION: acpi_ps_execute_method
64 : : *
65 : : * PARAMETERS: info - Method info block, contains:
66 : : * node - Method Node to execute
67 : : * obj_desc - Method object
68 : : * parameters - List of parameters to pass to the method,
69 : : * terminated by NULL. Params itself may be
70 : : * NULL if no parameters are being passed.
71 : : * return_object - Where to put method's return value (if
72 : : * any). If NULL, no value is returned.
73 : : * parameter_type - Type of Parameter list
74 : : * return_object - Where to put method's return value (if
75 : : * any). If NULL, no value is returned.
76 : : * pass_number - Parse or execute pass
77 : : *
78 : : * RETURN: Status
79 : : *
80 : : * DESCRIPTION: Execute a control method
81 : : *
82 : : ******************************************************************************/
83 : :
84 : 5661 : acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)
85 : : {
86 : 5661 : acpi_status status;
87 : 5661 : union acpi_parse_object *op;
88 : 5661 : struct acpi_walk_state *walk_state;
89 : :
90 : 5661 : ACPI_FUNCTION_TRACE(ps_execute_method);
91 : :
92 : : /* Quick validation of DSDT header */
93 : :
94 : 5661 : acpi_tb_check_dsdt_header();
95 : :
96 : : /* Validate the Info and method Node */
97 : :
98 [ + - + - ]: 5661 : if (!info || !info->node) {
99 : : return_ACPI_STATUS(AE_NULL_ENTRY);
100 : : }
101 : :
102 : : /* Init for new method, wait on concurrency semaphore */
103 : :
104 : 5661 : status =
105 : 5661 : acpi_ds_begin_method_execution(info->node, info->obj_desc, NULL);
106 [ + - ]: 5661 : if (ACPI_FAILURE(status)) {
107 : : return_ACPI_STATUS(status);
108 : : }
109 : :
110 : : /*
111 : : * The caller "owns" the parameters, so give each one an extra reference
112 : : */
113 : 5661 : acpi_ps_update_parameter_list(info, REF_INCREMENT);
114 : :
115 : : /*
116 : : * Execute the method. Performs parse simultaneously
117 : : */
118 : : ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
119 : : "**** Begin Method Parse/Execute [%4.4s] **** Node=%p Obj=%p\n",
120 : 5661 : info->node->name.ascii, info->node, info->obj_desc));
121 : :
122 : : /* Create and init a Root Node */
123 : :
124 : 5661 : op = acpi_ps_create_scope_op(info->obj_desc->method.aml_start);
125 [ - + ]: 5661 : if (!op) {
126 : 0 : status = AE_NO_MEMORY;
127 : 0 : goto cleanup;
128 : : }
129 : :
130 : : /* Create and initialize a new walk state */
131 : :
132 : 5661 : info->pass_number = ACPI_IMODE_EXECUTE;
133 : 5661 : walk_state =
134 : 5661 : acpi_ds_create_walk_state(info->obj_desc->method.owner_id, NULL,
135 : : NULL, NULL);
136 [ - + ]: 5661 : if (!walk_state) {
137 : 0 : status = AE_NO_MEMORY;
138 : 0 : goto cleanup;
139 : : }
140 : :
141 : 5661 : status = acpi_ds_init_aml_walk(walk_state, op, info->node,
142 : : info->obj_desc->method.aml_start,
143 : 5661 : info->obj_desc->method.aml_length, info,
144 : 5661 : info->pass_number);
145 [ - + ]: 5661 : if (ACPI_FAILURE(status)) {
146 : 0 : acpi_ds_delete_walk_state(walk_state);
147 : 0 : goto cleanup;
148 : : }
149 : :
150 : 5661 : walk_state->method_pathname = info->full_pathname;
151 : 5661 : walk_state->method_is_nested = FALSE;
152 : :
153 [ - + ]: 5661 : if (info->obj_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL) {
154 : 0 : walk_state->parse_flags |= ACPI_PARSE_MODULE_LEVEL;
155 : : }
156 : :
157 : : /* Invoke an internal method if necessary */
158 : :
159 [ - + ]: 5661 : if (info->obj_desc->method.info_flags & ACPI_METHOD_INTERNAL_ONLY) {
160 : 0 : status =
161 : 0 : info->obj_desc->method.dispatch.implementation(walk_state);
162 : 0 : info->return_object = walk_state->return_desc;
163 : :
164 : : /* Cleanup states */
165 : :
166 : 0 : acpi_ds_scope_stack_clear(walk_state);
167 : 0 : acpi_ps_cleanup_scope(&walk_state->parser_state);
168 : 0 : acpi_ds_terminate_control_method(walk_state->method_desc,
169 : : walk_state);
170 : 0 : acpi_ds_delete_walk_state(walk_state);
171 : 0 : goto cleanup;
172 : : }
173 : :
174 : : /*
175 : : * Start method evaluation with an implicit return of zero.
176 : : * This is done for Windows compatibility.
177 : : */
178 [ + - ]: 5661 : if (acpi_gbl_enable_interpreter_slack) {
179 : 11322 : walk_state->implicit_return_obj =
180 : 5661 : acpi_ut_create_integer_object((u64) 0);
181 [ - + ]: 5661 : if (!walk_state->implicit_return_obj) {
182 : 0 : status = AE_NO_MEMORY;
183 : 0 : acpi_ds_delete_walk_state(walk_state);
184 : 0 : goto cleanup;
185 : : }
186 : : }
187 : :
188 : : /* Parse the AML */
189 : :
190 : 5661 : status = acpi_ps_parse_aml(walk_state);
191 : :
192 : : /* walk_state was deleted by parse_aml */
193 : :
194 : 5661 : cleanup:
195 : 5661 : acpi_ps_delete_parse_tree(op);
196 : :
197 : : /* Take away the extra reference that we gave the parameters above */
198 : :
199 : 5661 : acpi_ps_update_parameter_list(info, REF_DECREMENT);
200 : :
201 : : /* Exit now if error above */
202 : :
203 [ + - ]: 5661 : if (ACPI_FAILURE(status)) {
204 : : return_ACPI_STATUS(status);
205 : : }
206 : :
207 : : /*
208 : : * If the method has returned an object, signal this to the caller with
209 : : * a control exception code
210 : : */
211 [ + - ]: 5661 : if (info->return_object) {
212 : : ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Method returned ObjDesc=%p\n",
213 : 5661 : info->return_object));
214 : 5661 : ACPI_DUMP_STACK_ENTRY(info->return_object);
215 : :
216 : 5661 : status = AE_CTRL_RETURN_VALUE;
217 : : }
218 : :
219 : : return_ACPI_STATUS(status);
220 : : }
221 : :
222 : : /*******************************************************************************
223 : : *
224 : : * FUNCTION: acpi_ps_execute_table
225 : : *
226 : : * PARAMETERS: info - Method info block, contains:
227 : : * node - Node to where the is entered into the
228 : : * namespace
229 : : * obj_desc - Pseudo method object describing the AML
230 : : * code of the entire table
231 : : * pass_number - Parse or execute pass
232 : : *
233 : : * RETURN: Status
234 : : *
235 : : * DESCRIPTION: Execute a table
236 : : *
237 : : ******************************************************************************/
238 : :
239 : 78 : acpi_status acpi_ps_execute_table(struct acpi_evaluate_info *info)
240 : : {
241 : 78 : acpi_status status;
242 : 78 : union acpi_parse_object *op = NULL;
243 : 78 : struct acpi_walk_state *walk_state = NULL;
244 : :
245 : 78 : ACPI_FUNCTION_TRACE(ps_execute_table);
246 : :
247 : : /* Create and init a Root Node */
248 : :
249 : 78 : op = acpi_ps_create_scope_op(info->obj_desc->method.aml_start);
250 [ - + ]: 78 : if (!op) {
251 : 0 : status = AE_NO_MEMORY;
252 : 0 : goto cleanup;
253 : : }
254 : :
255 : : /* Create and initialize a new walk state */
256 : :
257 : 78 : walk_state =
258 : 78 : acpi_ds_create_walk_state(info->obj_desc->method.owner_id, NULL,
259 : : NULL, NULL);
260 [ - + ]: 78 : if (!walk_state) {
261 : 0 : status = AE_NO_MEMORY;
262 : 0 : goto cleanup;
263 : : }
264 : :
265 : 78 : status = acpi_ds_init_aml_walk(walk_state, op, info->node,
266 : : info->obj_desc->method.aml_start,
267 : 78 : info->obj_desc->method.aml_length, info,
268 : 78 : info->pass_number);
269 [ - + ]: 78 : if (ACPI_FAILURE(status)) {
270 : 0 : goto cleanup;
271 : : }
272 : :
273 : 78 : walk_state->method_pathname = info->full_pathname;
274 : 78 : walk_state->method_is_nested = FALSE;
275 : :
276 [ + - ]: 78 : if (info->obj_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL) {
277 : 78 : walk_state->parse_flags |= ACPI_PARSE_MODULE_LEVEL;
278 : : }
279 : :
280 : : /* Info->Node is the default location to load the table */
281 : :
282 [ + - - + ]: 78 : if (info->node && info->node != acpi_gbl_root_node) {
283 : 0 : status =
284 : 0 : acpi_ds_scope_stack_push(info->node, ACPI_TYPE_METHOD,
285 : : walk_state);
286 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
287 : 0 : goto cleanup;
288 : : }
289 : : }
290 : :
291 : : /*
292 : : * Parse the AML, walk_state will be deleted by parse_aml
293 : : */
294 : 78 : acpi_ex_enter_interpreter();
295 : 78 : status = acpi_ps_parse_aml(walk_state);
296 : 78 : acpi_ex_exit_interpreter();
297 : 78 : walk_state = NULL;
298 : :
299 : 0 : cleanup:
300 [ - - ]: 78 : if (walk_state) {
301 : 0 : acpi_ds_delete_walk_state(walk_state);
302 : : }
303 [ + - ]: 78 : if (op) {
304 : 78 : acpi_ps_delete_parse_tree(op);
305 : : }
306 : 78 : return_ACPI_STATUS(status);
307 : : }
308 : :
309 : : /*******************************************************************************
310 : : *
311 : : * FUNCTION: acpi_ps_update_parameter_list
312 : : *
313 : : * PARAMETERS: info - See struct acpi_evaluate_info
314 : : * (Used: parameter_type and Parameters)
315 : : * action - Add or Remove reference
316 : : *
317 : : * RETURN: Status
318 : : *
319 : : * DESCRIPTION: Update reference count on all method parameter objects
320 : : *
321 : : ******************************************************************************/
322 : :
323 : : static void
324 : 11322 : acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action)
325 : : {
326 : 11322 : u32 i;
327 : :
328 [ + + ]: 11322 : if (info->parameters) {
329 : :
330 : : /* Update reference count for each parameter */
331 : :
332 [ + + ]: 312 : for (i = 0; info->parameters[i]; i++) {
333 : :
334 : : /* Ignore errors, just do them all */
335 : :
336 : 156 : (void)acpi_ut_update_object_reference(info->
337 : : parameters[i],
338 : : action);
339 : : }
340 : : }
341 : 11322 : }
|