1 /******************************************************************************
2  *
3  * Module Name: dsmethod - Parser/Interpreter interface - control method parsing
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2004, R. Byron Moore
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 
45 #include <acpi/acpi.h>
46 #include <acpi/acparser.h>
47 #include <acpi/amlcode.h>
48 #include <acpi/acdispat.h>
49 #include <acpi/acinterp.h>
50 #include <acpi/acnamesp.h>
51 
52 
53 #define _COMPONENT          ACPI_DISPATCHER
54 	 ACPI_MODULE_NAME    ("dsmethod")
55 
56 
57 /*******************************************************************************
58  *
59  * FUNCTION:    acpi_ds_parse_method
60  *
61  * PARAMETERS:  obj_handle      - Node of the method
62  *              Level           - Current nesting level
63  *              Context         - Points to a method counter
64  *              return_value    - Not used
65  *
66  * RETURN:      Status
67  *
68  * DESCRIPTION: Call the parser and parse the AML that is
69  *              associated with the method.
70  *
71  * MUTEX:       Assumes parser is locked
72  *
73  ******************************************************************************/
74 
75 acpi_status
acpi_ds_parse_method(acpi_handle obj_handle)76 acpi_ds_parse_method (
77 	acpi_handle                     obj_handle)
78 {
79 	acpi_status                     status;
80 	union acpi_operand_object       *obj_desc;
81 	union acpi_parse_object         *op;
82 	struct acpi_namespace_node      *node;
83 	acpi_owner_id                   owner_id;
84 	struct acpi_walk_state          *walk_state;
85 
86 
87 	ACPI_FUNCTION_TRACE_PTR ("ds_parse_method", obj_handle);
88 
89 
90 	/* Parameter Validation */
91 
92 	if (!obj_handle) {
93 		return_ACPI_STATUS (AE_NULL_ENTRY);
94 	}
95 
96 	ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Parsing [%4.4s] **** named_obj=%p\n",
97 		acpi_ut_get_node_name (obj_handle), obj_handle));
98 
99 	/* Extract the method object from the method Node */
100 
101 	node = (struct acpi_namespace_node *) obj_handle;
102 	obj_desc = acpi_ns_get_attached_object (node);
103 	if (!obj_desc) {
104 		return_ACPI_STATUS (AE_NULL_OBJECT);
105 	}
106 
107 	/* Create a mutex for the method if there is a concurrency limit */
108 
109 	if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) &&
110 		(!obj_desc->method.semaphore)) {
111 		status = acpi_os_create_semaphore (obj_desc->method.concurrency,
112 				   obj_desc->method.concurrency,
113 				   &obj_desc->method.semaphore);
114 		if (ACPI_FAILURE (status)) {
115 			return_ACPI_STATUS (status);
116 		}
117 	}
118 
119 	/*
120 	 * Allocate a new parser op to be the root of the parsed
121 	 * method tree
122 	 */
123 	op = acpi_ps_alloc_op (AML_METHOD_OP);
124 	if (!op) {
125 		return_ACPI_STATUS (AE_NO_MEMORY);
126 	}
127 
128 	/* Init new op with the method name and pointer back to the Node */
129 
130 	acpi_ps_set_name (op, node->name.integer);
131 	op->common.node = node;
132 
133 	/*
134 	 * Get a new owner_id for objects created by this method. Namespace
135 	 * objects (such as Operation Regions) can be created during the
136 	 * first pass parse.
137 	 */
138 	owner_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD);
139 	obj_desc->method.owning_id = owner_id;
140 
141 	/* Create and initialize a new walk state */
142 
143 	walk_state = acpi_ds_create_walk_state (owner_id, NULL, NULL, NULL);
144 	if (!walk_state) {
145 		return_ACPI_STATUS (AE_NO_MEMORY);
146 	}
147 
148 	status = acpi_ds_init_aml_walk (walk_state, op, node, obj_desc->method.aml_start,
149 			  obj_desc->method.aml_length, NULL, NULL, 1);
150 	if (ACPI_FAILURE (status)) {
151 		acpi_ds_delete_walk_state (walk_state);
152 		return_ACPI_STATUS (status);
153 	}
154 
155 	/*
156 	 * Parse the method, first pass
157 	 *
158 	 * The first pass load is where newly declared named objects are
159 	 * added into the namespace.  Actual evaluation of
160 	 * the named objects (what would be called a "second
161 	 * pass") happens during the actual execution of the
162 	 * method so that operands to the named objects can
163 	 * take on dynamic run-time values.
164 	 */
165 	status = acpi_ps_parse_aml (walk_state);
166 	if (ACPI_FAILURE (status)) {
167 		return_ACPI_STATUS (status);
168 	}
169 
170 	ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
171 		"**** [%4.4s] Parsed **** named_obj=%p Op=%p\n",
172 		acpi_ut_get_node_name (obj_handle), obj_handle, op));
173 
174 	acpi_ps_delete_parse_tree (op);
175 	return_ACPI_STATUS (status);
176 }
177 
178 
179 /*******************************************************************************
180  *
181  * FUNCTION:    acpi_ds_begin_method_execution
182  *
183  * PARAMETERS:  method_node         - Node of the method
184  *              obj_desc            - The method object
185  *              calling_method_node - Caller of this method (if non-null)
186  *
187  * RETURN:      Status
188  *
189  * DESCRIPTION: Prepare a method for execution.  Parses the method if necessary,
190  *              increments the thread count, and waits at the method semaphore
191  *              for clearance to execute.
192  *
193  * MUTEX:       Locks/unlocks parser.
194  *
195  ******************************************************************************/
196 
197 acpi_status
acpi_ds_begin_method_execution(struct acpi_namespace_node * method_node,union acpi_operand_object * obj_desc,struct acpi_namespace_node * calling_method_node)198 acpi_ds_begin_method_execution (
199 	struct acpi_namespace_node      *method_node,
200 	union acpi_operand_object       *obj_desc,
201 	struct acpi_namespace_node      *calling_method_node)
202 {
203 	acpi_status                     status = AE_OK;
204 
205 
206 	ACPI_FUNCTION_TRACE_PTR ("ds_begin_method_execution", method_node);
207 
208 
209 	if (!method_node) {
210 		return_ACPI_STATUS (AE_NULL_ENTRY);
211 	}
212 
213 	/*
214 	 * If there is a concurrency limit on this method, we need to
215 	 * obtain a unit from the method semaphore.
216 	 */
217 	if (obj_desc->method.semaphore) {
218 		/*
219 		 * Allow recursive method calls, up to the reentrancy/concurrency
220 		 * limit imposed by the SERIALIZED rule and the sync_level method
221 		 * parameter.
222 		 *
223 		 * The point of this code is to avoid permanently blocking a
224 		 * thread that is making recursive method calls.
225 		 */
226 		if (method_node == calling_method_node) {
227 			if (obj_desc->method.thread_count >= obj_desc->method.concurrency) {
228 				return_ACPI_STATUS (AE_AML_METHOD_LIMIT);
229 			}
230 		}
231 
232 		/*
233 		 * Get a unit from the method semaphore. This releases the
234 		 * interpreter if we block
235 		 */
236 		status = acpi_ex_system_wait_semaphore (obj_desc->method.semaphore,
237 				 ACPI_WAIT_FOREVER);
238 	}
239 
240 	/*
241 	 * Increment the method parse tree thread count since it has been
242 	 * reentered one more time (even if it is the same thread)
243 	 */
244 	obj_desc->method.thread_count++;
245 	return_ACPI_STATUS (status);
246 }
247 
248 
249 /*******************************************************************************
250  *
251  * FUNCTION:    acpi_ds_call_control_method
252  *
253  * PARAMETERS:  walk_state          - Current state of the walk
254  *              Op                  - Current Op to be walked
255  *
256  * RETURN:      Status
257  *
258  * DESCRIPTION: Transfer execution to a called control method
259  *
260  ******************************************************************************/
261 
262 acpi_status
acpi_ds_call_control_method(struct acpi_thread_state * thread,struct acpi_walk_state * this_walk_state,union acpi_parse_object * op)263 acpi_ds_call_control_method (
264 	struct acpi_thread_state        *thread,
265 	struct acpi_walk_state          *this_walk_state,
266 	union acpi_parse_object         *op)
267 {
268 	acpi_status                     status;
269 	struct acpi_namespace_node      *method_node;
270 	union acpi_operand_object       *obj_desc;
271 	struct acpi_walk_state          *next_walk_state;
272 	u32                             i;
273 
274 
275 	ACPI_FUNCTION_TRACE_PTR ("ds_call_control_method", this_walk_state);
276 
277 	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Execute method %p, currentstate=%p\n",
278 		this_walk_state->prev_op, this_walk_state));
279 
280 	/*
281 	 * Get the namespace entry for the control method we are about to call
282 	 */
283 	method_node = this_walk_state->method_call_node;
284 	if (!method_node) {
285 		return_ACPI_STATUS (AE_NULL_ENTRY);
286 	}
287 
288 	obj_desc = acpi_ns_get_attached_object (method_node);
289 	if (!obj_desc) {
290 		return_ACPI_STATUS (AE_NULL_OBJECT);
291 	}
292 
293 	obj_desc->method.owning_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD);
294 
295 	/* Init for new method, wait on concurrency semaphore */
296 
297 	status = acpi_ds_begin_method_execution (method_node, obj_desc,
298 			  this_walk_state->method_node);
299 	if (ACPI_FAILURE (status)) {
300 		return_ACPI_STATUS (status);
301 	}
302 
303 	if (!(obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY)) {
304 		/* 1) Parse: Create a new walk state for the preempting walk */
305 
306 		next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id,
307 				  op, obj_desc, NULL);
308 		if (!next_walk_state) {
309 			return_ACPI_STATUS (AE_NO_MEMORY);
310 		}
311 
312 
313 		/* Create and init a Root Node */
314 
315 		op = acpi_ps_create_scope_op ();
316 		if (!op) {
317 			status = AE_NO_MEMORY;
318 			goto cleanup;
319 		}
320 
321 		status = acpi_ds_init_aml_walk (next_walk_state, op, method_node,
322 				  obj_desc->method.aml_start, obj_desc->method.aml_length,
323 				  NULL, NULL, 1);
324 		if (ACPI_FAILURE (status)) {
325 			acpi_ds_delete_walk_state (next_walk_state);
326 			goto cleanup;
327 		}
328 
329 		/* Begin AML parse */
330 
331 		status = acpi_ps_parse_aml (next_walk_state);
332 		acpi_ps_delete_parse_tree (op);
333 	}
334 
335 	/* 2) Execute: Create a new state for the preempting walk */
336 
337 	next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id,
338 			  NULL, obj_desc, thread);
339 	if (!next_walk_state) {
340 		status = AE_NO_MEMORY;
341 		goto cleanup;
342 	}
343 	/*
344 	 * The resolved arguments were put on the previous walk state's operand
345 	 * stack.  Operands on the previous walk state stack always
346 	 * start at index 0.
347 	 * Null terminate the list of arguments
348 	 */
349 	this_walk_state->operands [this_walk_state->num_operands] = NULL;
350 
351 	status = acpi_ds_init_aml_walk (next_walk_state, NULL, method_node,
352 			  obj_desc->method.aml_start, obj_desc->method.aml_length,
353 			  &this_walk_state->operands[0], NULL, 3);
354 	if (ACPI_FAILURE (status)) {
355 		goto cleanup;
356 	}
357 
358 	/*
359 	 * Delete the operands on the previous walkstate operand stack
360 	 * (they were copied to new objects)
361 	 */
362 	for (i = 0; i < obj_desc->method.param_count; i++) {
363 		acpi_ut_remove_reference (this_walk_state->operands [i]);
364 		this_walk_state->operands [i] = NULL;
365 	}
366 
367 	/* Clear the operand stack */
368 
369 	this_walk_state->num_operands = 0;
370 
371 	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
372 		"Starting nested execution, newstate=%p\n", next_walk_state));
373 
374 	if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
375 		status = obj_desc->method.implementation (next_walk_state);
376 		return_ACPI_STATUS (status);
377 	}
378 
379 	return_ACPI_STATUS (AE_OK);
380 
381 
382 	/* On error, we must delete the new walk state */
383 
384 cleanup:
385 	if (next_walk_state->method_desc) {
386 		/* Decrement the thread count on the method parse tree */
387 
388 	   next_walk_state->method_desc->method.thread_count--;
389 	}
390 	(void) acpi_ds_terminate_control_method (next_walk_state);
391 	acpi_ds_delete_walk_state (next_walk_state);
392 	return_ACPI_STATUS (status);
393 }
394 
395 
396 /*******************************************************************************
397  *
398  * FUNCTION:    acpi_ds_restart_control_method
399  *
400  * PARAMETERS:  walk_state          - State of the method when it was preempted
401  *              Op                  - Pointer to new current op
402  *
403  * RETURN:      Status
404  *
405  * DESCRIPTION: Restart a method that was preempted
406  *
407  ******************************************************************************/
408 
409 acpi_status
acpi_ds_restart_control_method(struct acpi_walk_state * walk_state,union acpi_operand_object * return_desc)410 acpi_ds_restart_control_method (
411 	struct acpi_walk_state          *walk_state,
412 	union acpi_operand_object       *return_desc)
413 {
414 	acpi_status                     status;
415 
416 
417 	ACPI_FUNCTION_TRACE_PTR ("ds_restart_control_method", walk_state);
418 
419 
420 	if (return_desc) {
421 		if (walk_state->return_used) {
422 			/*
423 			 * Get the return value (if any) from the previous method.
424 			 * NULL if no return value
425 			 */
426 			status = acpi_ds_result_push (return_desc, walk_state);
427 			if (ACPI_FAILURE (status)) {
428 				acpi_ut_remove_reference (return_desc);
429 				return_ACPI_STATUS (status);
430 			}
431 		}
432 		else {
433 			/*
434 			 * Delete the return value if it will not be used by the
435 			 * calling method
436 			 */
437 			acpi_ut_remove_reference (return_desc);
438 		}
439 	}
440 
441 	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
442 		"Method=%p Return=%p return_used?=%X res_stack=%p State=%p\n",
443 		walk_state->method_call_op, return_desc, walk_state->return_used,
444 		walk_state->results, walk_state));
445 
446 	return_ACPI_STATUS (AE_OK);
447 }
448 
449 
450 /*******************************************************************************
451  *
452  * FUNCTION:    acpi_ds_terminate_control_method
453  *
454  * PARAMETERS:  walk_state          - State of the method
455  *
456  * RETURN:      Status
457  *
458  * DESCRIPTION: Terminate a control method.  Delete everything that the method
459  *              created, delete all locals and arguments, and delete the parse
460  *              tree if requested.
461  *
462  ******************************************************************************/
463 
464 acpi_status
acpi_ds_terminate_control_method(struct acpi_walk_state * walk_state)465 acpi_ds_terminate_control_method (
466 	struct acpi_walk_state          *walk_state)
467 {
468 	union acpi_operand_object       *obj_desc;
469 	struct acpi_namespace_node      *method_node;
470 	acpi_status                     status;
471 
472 
473 	ACPI_FUNCTION_TRACE_PTR ("ds_terminate_control_method", walk_state);
474 
475 
476 	if (!walk_state) {
477 		return (AE_BAD_PARAMETER);
478 	}
479 
480 	/* The current method object was saved in the walk state */
481 
482 	obj_desc = walk_state->method_desc;
483 	if (!obj_desc) {
484 		return_ACPI_STATUS (AE_OK);
485 	}
486 
487 	/* Delete all arguments and locals */
488 
489 	acpi_ds_method_data_delete_all (walk_state);
490 
491 	/*
492 	 * Lock the parser while we terminate this method.
493 	 * If this is the last thread executing the method,
494 	 * we have additional cleanup to perform
495 	 */
496 	status = acpi_ut_acquire_mutex (ACPI_MTX_PARSER);
497 	if (ACPI_FAILURE (status)) {
498 		return_ACPI_STATUS (status);
499 	}
500 
501 	/* Signal completion of the execution of this method if necessary */
502 
503 	if (walk_state->method_desc->method.semaphore) {
504 		status = acpi_os_signal_semaphore (
505 				  walk_state->method_desc->method.semaphore, 1);
506 		if (ACPI_FAILURE (status)) {
507 			ACPI_REPORT_ERROR (("Could not signal method semaphore\n"));
508 			status = AE_OK;
509 
510 			/* Ignore error and continue cleanup */
511 		}
512 	}
513 
514 	if (walk_state->method_desc->method.thread_count) {
515 		ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
516 			"*** Not deleting method namespace, there are still %d threads\n",
517 			walk_state->method_desc->method.thread_count));
518 	}
519 
520 	if (!walk_state->method_desc->method.thread_count) {
521 		/*
522 		 * Support to dynamically change a method from not_serialized to
523 		 * Serialized if it appears that the method is written foolishly and
524 		 * does not support multiple thread execution.  The best example of this
525 		 * is if such a method creates namespace objects and blocks.  A second
526 		 * thread will fail with an AE_ALREADY_EXISTS exception
527 		 *
528 		 * This code is here because we must wait until the last thread exits
529 		 * before creating the synchronization semaphore.
530 		 */
531 		if ((walk_state->method_desc->method.concurrency == 1) &&
532 			(!walk_state->method_desc->method.semaphore)) {
533 			status = acpi_os_create_semaphore (1,
534 					 1,
535 					 &walk_state->method_desc->method.semaphore);
536 		}
537 
538 		/*
539 		 * There are no more threads executing this method.  Perform
540 		 * additional cleanup.
541 		 *
542 		 * The method Node is stored in the walk state
543 		 */
544 		method_node = walk_state->method_node;
545 
546 		/*
547 		 * Delete any namespace entries created immediately underneath
548 		 * the method
549 		 */
550 		status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
551 		if (ACPI_FAILURE (status)) {
552 			return_ACPI_STATUS (status);
553 		}
554 
555 		if (method_node->child) {
556 			acpi_ns_delete_namespace_subtree (method_node);
557 		}
558 
559 		/*
560 		 * Delete any namespace entries created anywhere else within
561 		 * the namespace
562 		 */
563 		acpi_ns_delete_namespace_by_owner (walk_state->method_desc->method.owning_id);
564 		status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
565 		if (ACPI_FAILURE (status)) {
566 			return_ACPI_STATUS (status);
567 		}
568 	}
569 
570 	status = acpi_ut_release_mutex (ACPI_MTX_PARSER);
571 	return_ACPI_STATUS (status);
572 }
573 
574 
575