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