xref: /linux/drivers/acpi/acpica/exresolv.c (revision d524dac9279b6a41ffdf7ff7958c577f2e387db6)
1 
2 /******************************************************************************
3  *
4  * Module Name: exresolv - AML Interpreter object resolution
5  *
6  *****************************************************************************/
7 
8 /*
9  * Copyright (C) 2000 - 2011, Intel Corp.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions, and the following disclaimer,
17  *    without modification.
18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19  *    substantially similar to the "NO WARRANTY" disclaimer below
20  *    ("Disclaimer") and any redistribution must be conditioned upon
21  *    including a substantially similar Disclaimer requirement for further
22  *    binary redistribution.
23  * 3. Neither the names of the above-listed copyright holders nor the names
24  *    of any contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * Alternatively, this software may be distributed under the terms of the
28  * GNU General Public License ("GPL") version 2 as published by the Free
29  * Software Foundation.
30  *
31  * NO WARRANTY
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42  * POSSIBILITY OF SUCH DAMAGES.
43  */
44 
45 #include <acpi/acpi.h>
46 #include "accommon.h"
47 #include "amlcode.h"
48 #include "acdispat.h"
49 #include "acinterp.h"
50 #include "acnamesp.h"
51 
52 #define _COMPONENT          ACPI_EXECUTER
53 ACPI_MODULE_NAME("exresolv")
54 
55 /* Local prototypes */
56 static acpi_status
57 acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
58 				struct acpi_walk_state *walk_state);
59 
60 /*******************************************************************************
61  *
62  * FUNCTION:    acpi_ex_resolve_to_value
63  *
64  * PARAMETERS:  **stack_ptr         - Points to entry on obj_stack, which can
65  *                                    be either an (union acpi_operand_object *)
66  *                                    or an acpi_handle.
67  *              walk_state          - Current method state
68  *
69  * RETURN:      Status
70  *
71  * DESCRIPTION: Convert Reference objects to values
72  *
73  ******************************************************************************/
74 
75 acpi_status
76 acpi_ex_resolve_to_value(union acpi_operand_object **stack_ptr,
77 			 struct acpi_walk_state *walk_state)
78 {
79 	acpi_status status;
80 
81 	ACPI_FUNCTION_TRACE_PTR(ex_resolve_to_value, stack_ptr);
82 
83 	if (!stack_ptr || !*stack_ptr) {
84 		ACPI_ERROR((AE_INFO, "Internal - null pointer"));
85 		return_ACPI_STATUS(AE_AML_NO_OPERAND);
86 	}
87 
88 	/*
89 	 * The entity pointed to by the stack_ptr can be either
90 	 * 1) A valid union acpi_operand_object, or
91 	 * 2) A struct acpi_namespace_node (named_obj)
92 	 */
93 	if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_OPERAND) {
94 		status = acpi_ex_resolve_object_to_value(stack_ptr, walk_state);
95 		if (ACPI_FAILURE(status)) {
96 			return_ACPI_STATUS(status);
97 		}
98 
99 		if (!*stack_ptr) {
100 			ACPI_ERROR((AE_INFO, "Internal - null pointer"));
101 			return_ACPI_STATUS(AE_AML_NO_OPERAND);
102 		}
103 	}
104 
105 	/*
106 	 * Object on the stack may have changed if acpi_ex_resolve_object_to_value()
107 	 * was called (i.e., we can't use an _else_ here.)
108 	 */
109 	if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_NAMED) {
110 		status =
111 		    acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR
112 						  (struct acpi_namespace_node,
113 						   stack_ptr), walk_state);
114 		if (ACPI_FAILURE(status)) {
115 			return_ACPI_STATUS(status);
116 		}
117 	}
118 
119 	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Resolved object %p\n", *stack_ptr));
120 	return_ACPI_STATUS(AE_OK);
121 }
122 
123 /*******************************************************************************
124  *
125  * FUNCTION:    acpi_ex_resolve_object_to_value
126  *
127  * PARAMETERS:  stack_ptr       - Pointer to an internal object
128  *              walk_state      - Current method state
129  *
130  * RETURN:      Status
131  *
132  * DESCRIPTION: Retrieve the value from an internal object. The Reference type
133  *              uses the associated AML opcode to determine the value.
134  *
135  ******************************************************************************/
136 
137 static acpi_status
138 acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
139 				struct acpi_walk_state *walk_state)
140 {
141 	acpi_status status = AE_OK;
142 	union acpi_operand_object *stack_desc;
143 	union acpi_operand_object *obj_desc = NULL;
144 	u8 ref_type;
145 
146 	ACPI_FUNCTION_TRACE(ex_resolve_object_to_value);
147 
148 	stack_desc = *stack_ptr;
149 
150 	/* This is a union acpi_operand_object    */
151 
152 	switch (stack_desc->common.type) {
153 	case ACPI_TYPE_LOCAL_REFERENCE:
154 
155 		ref_type = stack_desc->reference.class;
156 
157 		switch (ref_type) {
158 		case ACPI_REFCLASS_LOCAL:
159 		case ACPI_REFCLASS_ARG:
160 
161 			/*
162 			 * Get the local from the method's state info
163 			 * Note: this increments the local's object reference count
164 			 */
165 			status = acpi_ds_method_data_get_value(ref_type,
166 							       stack_desc->
167 							       reference.value,
168 							       walk_state,
169 							       &obj_desc);
170 			if (ACPI_FAILURE(status)) {
171 				return_ACPI_STATUS(status);
172 			}
173 
174 			ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
175 					  "[Arg/Local %X] ValueObj is %p\n",
176 					  stack_desc->reference.value,
177 					  obj_desc));
178 
179 			/*
180 			 * Now we can delete the original Reference Object and
181 			 * replace it with the resolved value
182 			 */
183 			acpi_ut_remove_reference(stack_desc);
184 			*stack_ptr = obj_desc;
185 			break;
186 
187 		case ACPI_REFCLASS_INDEX:
188 
189 			switch (stack_desc->reference.target_type) {
190 			case ACPI_TYPE_BUFFER_FIELD:
191 
192 				/* Just return - do not dereference */
193 				break;
194 
195 			case ACPI_TYPE_PACKAGE:
196 
197 				/* If method call or copy_object - do not dereference */
198 
199 				if ((walk_state->opcode ==
200 				     AML_INT_METHODCALL_OP)
201 				    || (walk_state->opcode == AML_COPY_OP)) {
202 					break;
203 				}
204 
205 				/* Otherwise, dereference the package_index to a package element */
206 
207 				obj_desc = *stack_desc->reference.where;
208 				if (obj_desc) {
209 					/*
210 					 * Valid object descriptor, copy pointer to return value
211 					 * (i.e., dereference the package index)
212 					 * Delete the ref object, increment the returned object
213 					 */
214 					acpi_ut_remove_reference(stack_desc);
215 					acpi_ut_add_reference(obj_desc);
216 					*stack_ptr = obj_desc;
217 				} else {
218 					/*
219 					 * A NULL object descriptor means an uninitialized element of
220 					 * the package, can't dereference it
221 					 */
222 					ACPI_ERROR((AE_INFO,
223 						    "Attempt to dereference an Index to NULL package element Idx=%p",
224 						    stack_desc));
225 					status = AE_AML_UNINITIALIZED_ELEMENT;
226 				}
227 				break;
228 
229 			default:
230 
231 				/* Invalid reference object */
232 
233 				ACPI_ERROR((AE_INFO,
234 					    "Unknown TargetType 0x%X in Index/Reference object %p",
235 					    stack_desc->reference.target_type,
236 					    stack_desc));
237 				status = AE_AML_INTERNAL;
238 				break;
239 			}
240 			break;
241 
242 		case ACPI_REFCLASS_REFOF:
243 		case ACPI_REFCLASS_DEBUG:
244 		case ACPI_REFCLASS_TABLE:
245 
246 			/* Just leave the object as-is, do not dereference */
247 
248 			break;
249 
250 		case ACPI_REFCLASS_NAME:	/* Reference to a named object */
251 
252 			/* Dereference the name */
253 
254 			if ((stack_desc->reference.node->type ==
255 			     ACPI_TYPE_DEVICE)
256 			    || (stack_desc->reference.node->type ==
257 				ACPI_TYPE_THERMAL)) {
258 
259 				/* These node types do not have 'real' subobjects */
260 
261 				*stack_ptr = (void *)stack_desc->reference.node;
262 			} else {
263 				/* Get the object pointed to by the namespace node */
264 
265 				*stack_ptr =
266 				    (stack_desc->reference.node)->object;
267 				acpi_ut_add_reference(*stack_ptr);
268 			}
269 
270 			acpi_ut_remove_reference(stack_desc);
271 			break;
272 
273 		default:
274 
275 			ACPI_ERROR((AE_INFO,
276 				    "Unknown Reference type 0x%X in %p",
277 				    ref_type, stack_desc));
278 			status = AE_AML_INTERNAL;
279 			break;
280 		}
281 		break;
282 
283 	case ACPI_TYPE_BUFFER:
284 
285 		status = acpi_ds_get_buffer_arguments(stack_desc);
286 		break;
287 
288 	case ACPI_TYPE_PACKAGE:
289 
290 		status = acpi_ds_get_package_arguments(stack_desc);
291 		break;
292 
293 	case ACPI_TYPE_BUFFER_FIELD:
294 	case ACPI_TYPE_LOCAL_REGION_FIELD:
295 	case ACPI_TYPE_LOCAL_BANK_FIELD:
296 	case ACPI_TYPE_LOCAL_INDEX_FIELD:
297 
298 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
299 				  "FieldRead SourceDesc=%p Type=%X\n",
300 				  stack_desc, stack_desc->common.type));
301 
302 		status =
303 		    acpi_ex_read_data_from_field(walk_state, stack_desc,
304 						 &obj_desc);
305 
306 		/* Remove a reference to the original operand, then override */
307 
308 		acpi_ut_remove_reference(*stack_ptr);
309 		*stack_ptr = (void *)obj_desc;
310 		break;
311 
312 	default:
313 		break;
314 	}
315 
316 	return_ACPI_STATUS(status);
317 }
318 
319 /*******************************************************************************
320  *
321  * FUNCTION:    acpi_ex_resolve_multiple
322  *
323  * PARAMETERS:  walk_state          - Current state (contains AML opcode)
324  *              Operand             - Starting point for resolution
325  *              return_type         - Where the object type is returned
326  *              return_desc         - Where the resolved object is returned
327  *
328  * RETURN:      Status
329  *
330  * DESCRIPTION: Return the base object and type.  Traverse a reference list if
331  *              necessary to get to the base object.
332  *
333  ******************************************************************************/
334 
335 acpi_status
336 acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
337 			 union acpi_operand_object *operand,
338 			 acpi_object_type * return_type,
339 			 union acpi_operand_object **return_desc)
340 {
341 	union acpi_operand_object *obj_desc = (void *)operand;
342 	struct acpi_namespace_node *node;
343 	acpi_object_type type;
344 	acpi_status status;
345 
346 	ACPI_FUNCTION_TRACE(acpi_ex_resolve_multiple);
347 
348 	/* Operand can be either a namespace node or an operand descriptor */
349 
350 	switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
351 	case ACPI_DESC_TYPE_OPERAND:
352 		type = obj_desc->common.type;
353 		break;
354 
355 	case ACPI_DESC_TYPE_NAMED:
356 		type = ((struct acpi_namespace_node *)obj_desc)->type;
357 		obj_desc =
358 		    acpi_ns_get_attached_object((struct acpi_namespace_node *)
359 						obj_desc);
360 
361 		/* If we had an Alias node, use the attached object for type info */
362 
363 		if (type == ACPI_TYPE_LOCAL_ALIAS) {
364 			type = ((struct acpi_namespace_node *)obj_desc)->type;
365 			obj_desc =
366 			    acpi_ns_get_attached_object((struct
367 							 acpi_namespace_node *)
368 							obj_desc);
369 		}
370 		break;
371 
372 	default:
373 		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
374 	}
375 
376 	/* If type is anything other than a reference, we are done */
377 
378 	if (type != ACPI_TYPE_LOCAL_REFERENCE) {
379 		goto exit;
380 	}
381 
382 	/*
383 	 * For reference objects created via the ref_of, Index, or Load/load_table
384 	 * operators, we need to get to the base object (as per the ACPI
385 	 * specification of the object_type and size_of operators). This means
386 	 * traversing the list of possibly many nested references.
387 	 */
388 	while (obj_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) {
389 		switch (obj_desc->reference.class) {
390 		case ACPI_REFCLASS_REFOF:
391 		case ACPI_REFCLASS_NAME:
392 
393 			/* Dereference the reference pointer */
394 
395 			if (obj_desc->reference.class == ACPI_REFCLASS_REFOF) {
396 				node = obj_desc->reference.object;
397 			} else {	/* AML_INT_NAMEPATH_OP */
398 
399 				node = obj_desc->reference.node;
400 			}
401 
402 			/* All "References" point to a NS node */
403 
404 			if (ACPI_GET_DESCRIPTOR_TYPE(node) !=
405 			    ACPI_DESC_TYPE_NAMED) {
406 				ACPI_ERROR((AE_INFO,
407 					    "Not a namespace node %p [%s]",
408 					    node,
409 					    acpi_ut_get_descriptor_name(node)));
410 				return_ACPI_STATUS(AE_AML_INTERNAL);
411 			}
412 
413 			/* Get the attached object */
414 
415 			obj_desc = acpi_ns_get_attached_object(node);
416 			if (!obj_desc) {
417 
418 				/* No object, use the NS node type */
419 
420 				type = acpi_ns_get_type(node);
421 				goto exit;
422 			}
423 
424 			/* Check for circular references */
425 
426 			if (obj_desc == operand) {
427 				return_ACPI_STATUS(AE_AML_CIRCULAR_REFERENCE);
428 			}
429 			break;
430 
431 		case ACPI_REFCLASS_INDEX:
432 
433 			/* Get the type of this reference (index into another object) */
434 
435 			type = obj_desc->reference.target_type;
436 			if (type != ACPI_TYPE_PACKAGE) {
437 				goto exit;
438 			}
439 
440 			/*
441 			 * The main object is a package, we want to get the type
442 			 * of the individual package element that is referenced by
443 			 * the index.
444 			 *
445 			 * This could of course in turn be another reference object.
446 			 */
447 			obj_desc = *(obj_desc->reference.where);
448 			if (!obj_desc) {
449 
450 				/* NULL package elements are allowed */
451 
452 				type = 0;	/* Uninitialized */
453 				goto exit;
454 			}
455 			break;
456 
457 		case ACPI_REFCLASS_TABLE:
458 
459 			type = ACPI_TYPE_DDB_HANDLE;
460 			goto exit;
461 
462 		case ACPI_REFCLASS_LOCAL:
463 		case ACPI_REFCLASS_ARG:
464 
465 			if (return_desc) {
466 				status =
467 				    acpi_ds_method_data_get_value(obj_desc->
468 								  reference.
469 								  class,
470 								  obj_desc->
471 								  reference.
472 								  value,
473 								  walk_state,
474 								  &obj_desc);
475 				if (ACPI_FAILURE(status)) {
476 					return_ACPI_STATUS(status);
477 				}
478 				acpi_ut_remove_reference(obj_desc);
479 			} else {
480 				status =
481 				    acpi_ds_method_data_get_node(obj_desc->
482 								 reference.
483 								 class,
484 								 obj_desc->
485 								 reference.
486 								 value,
487 								 walk_state,
488 								 &node);
489 				if (ACPI_FAILURE(status)) {
490 					return_ACPI_STATUS(status);
491 				}
492 
493 				obj_desc = acpi_ns_get_attached_object(node);
494 				if (!obj_desc) {
495 					type = ACPI_TYPE_ANY;
496 					goto exit;
497 				}
498 			}
499 			break;
500 
501 		case ACPI_REFCLASS_DEBUG:
502 
503 			/* The Debug Object is of type "DebugObject" */
504 
505 			type = ACPI_TYPE_DEBUG_OBJECT;
506 			goto exit;
507 
508 		default:
509 
510 			ACPI_ERROR((AE_INFO,
511 				    "Unknown Reference Class 0x%2.2X",
512 				    obj_desc->reference.class));
513 			return_ACPI_STATUS(AE_AML_INTERNAL);
514 		}
515 	}
516 
517 	/*
518 	 * Now we are guaranteed to have an object that has not been created
519 	 * via the ref_of or Index operators.
520 	 */
521 	type = obj_desc->common.type;
522 
523       exit:
524 	/* Convert internal types to external types */
525 
526 	switch (type) {
527 	case ACPI_TYPE_LOCAL_REGION_FIELD:
528 	case ACPI_TYPE_LOCAL_BANK_FIELD:
529 	case ACPI_TYPE_LOCAL_INDEX_FIELD:
530 
531 		type = ACPI_TYPE_FIELD_UNIT;
532 		break;
533 
534 	case ACPI_TYPE_LOCAL_SCOPE:
535 
536 		/* Per ACPI Specification, Scope is untyped */
537 
538 		type = ACPI_TYPE_ANY;
539 		break;
540 
541 	default:
542 		/* No change to Type required */
543 		break;
544 	}
545 
546 	*return_type = type;
547 	if (return_desc) {
548 		*return_desc = obj_desc;
549 	}
550 	return_ACPI_STATUS(AE_OK);
551 }
552