1/******************************************************************************
2 *
3 * Module Name: exresolv - AML Interpreter object resolution
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2015, 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_add_reference(obj_desc);
213					*stack_ptr = obj_desc;
214				} else {
215					/*
216					 * A NULL object descriptor means an uninitialized element of
217					 * the package, can't dereference it
218					 */
219					ACPI_ERROR((AE_INFO,
220						    "Attempt to dereference an Index to NULL package element Idx=%p",
221						    stack_desc));
222					status = AE_AML_UNINITIALIZED_ELEMENT;
223				}
224				break;
225
226			default:
227
228				/* Invalid reference object */
229
230				ACPI_ERROR((AE_INFO,
231					    "Unknown TargetType 0x%X in Index/Reference object %p",
232					    stack_desc->reference.target_type,
233					    stack_desc));
234				status = AE_AML_INTERNAL;
235				break;
236			}
237			break;
238
239		case ACPI_REFCLASS_REFOF:
240		case ACPI_REFCLASS_DEBUG:
241		case ACPI_REFCLASS_TABLE:
242
243			/* Just leave the object as-is, do not dereference */
244
245			break;
246
247		case ACPI_REFCLASS_NAME:	/* Reference to a named object */
248
249			/* Dereference the name */
250
251			if ((stack_desc->reference.node->type ==
252			     ACPI_TYPE_DEVICE)
253			    || (stack_desc->reference.node->type ==
254				ACPI_TYPE_THERMAL)) {
255
256				/* These node types do not have 'real' subobjects */
257
258				*stack_ptr = (void *)stack_desc->reference.node;
259			} else {
260				/* Get the object pointed to by the namespace node */
261
262				*stack_ptr =
263				    (stack_desc->reference.node)->object;
264				acpi_ut_add_reference(*stack_ptr);
265			}
266
267			acpi_ut_remove_reference(stack_desc);
268			break;
269
270		default:
271
272			ACPI_ERROR((AE_INFO,
273				    "Unknown Reference type 0x%X in %p",
274				    ref_type, stack_desc));
275			status = AE_AML_INTERNAL;
276			break;
277		}
278		break;
279
280	case ACPI_TYPE_BUFFER:
281
282		status = acpi_ds_get_buffer_arguments(stack_desc);
283		break;
284
285	case ACPI_TYPE_PACKAGE:
286
287		status = acpi_ds_get_package_arguments(stack_desc);
288		break;
289
290	case ACPI_TYPE_BUFFER_FIELD:
291	case ACPI_TYPE_LOCAL_REGION_FIELD:
292	case ACPI_TYPE_LOCAL_BANK_FIELD:
293	case ACPI_TYPE_LOCAL_INDEX_FIELD:
294
295		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
296				  "FieldRead SourceDesc=%p Type=%X\n",
297				  stack_desc, stack_desc->common.type));
298
299		status =
300		    acpi_ex_read_data_from_field(walk_state, stack_desc,
301						 &obj_desc);
302
303		/* Remove a reference to the original operand, then override */
304
305		acpi_ut_remove_reference(*stack_ptr);
306		*stack_ptr = (void *)obj_desc;
307		break;
308
309	default:
310
311		break;
312	}
313
314	return_ACPI_STATUS(status);
315}
316
317/*******************************************************************************
318 *
319 * FUNCTION:    acpi_ex_resolve_multiple
320 *
321 * PARAMETERS:  walk_state          - Current state (contains AML opcode)
322 *              operand             - Starting point for resolution
323 *              return_type         - Where the object type is returned
324 *              return_desc         - Where the resolved object is returned
325 *
326 * RETURN:      Status
327 *
328 * DESCRIPTION: Return the base object and type. Traverse a reference list if
329 *              necessary to get to the base object.
330 *
331 ******************************************************************************/
332
333acpi_status
334acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
335			 union acpi_operand_object *operand,
336			 acpi_object_type * return_type,
337			 union acpi_operand_object **return_desc)
338{
339	union acpi_operand_object *obj_desc = ACPI_CAST_PTR(void, operand);
340	struct acpi_namespace_node *node =
341	    ACPI_CAST_PTR(struct acpi_namespace_node, operand);
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 = acpi_ns_get_attached_object(node);
359
360		/* If we had an Alias node, use the attached object for type info */
361
362		if (type == ACPI_TYPE_LOCAL_ALIAS) {
363			type = ((struct acpi_namespace_node *)obj_desc)->type;
364			obj_desc =
365			    acpi_ns_get_attached_object((struct
366							 acpi_namespace_node *)
367							obj_desc);
368		}
369
370		if (!obj_desc) {
371			ACPI_ERROR((AE_INFO,
372				    "[%4.4s] Node is unresolved or uninitialized",
373				    acpi_ut_get_node_name(node)));
374			return_ACPI_STATUS(AE_AML_UNINITIALIZED_NODE);
375		}
376		break;
377
378	default:
379		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
380	}
381
382	/* If type is anything other than a reference, we are done */
383
384	if (type != ACPI_TYPE_LOCAL_REFERENCE) {
385		goto exit;
386	}
387
388	/*
389	 * For reference objects created via the ref_of, Index, or Load/load_table
390	 * operators, we need to get to the base object (as per the ACPI
391	 * specification of the object_type and size_of operators). This means
392	 * traversing the list of possibly many nested references.
393	 */
394	while (obj_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) {
395		switch (obj_desc->reference.class) {
396		case ACPI_REFCLASS_REFOF:
397		case ACPI_REFCLASS_NAME:
398
399			/* Dereference the reference pointer */
400
401			if (obj_desc->reference.class == ACPI_REFCLASS_REFOF) {
402				node = obj_desc->reference.object;
403			} else {	/* AML_INT_NAMEPATH_OP */
404
405				node = obj_desc->reference.node;
406			}
407
408			/* All "References" point to a NS node */
409
410			if (ACPI_GET_DESCRIPTOR_TYPE(node) !=
411			    ACPI_DESC_TYPE_NAMED) {
412				ACPI_ERROR((AE_INFO,
413					    "Not a namespace node %p [%s]",
414					    node,
415					    acpi_ut_get_descriptor_name(node)));
416				return_ACPI_STATUS(AE_AML_INTERNAL);
417			}
418
419			/* Get the attached object */
420
421			obj_desc = acpi_ns_get_attached_object(node);
422			if (!obj_desc) {
423
424				/* No object, use the NS node type */
425
426				type = acpi_ns_get_type(node);
427				goto exit;
428			}
429
430			/* Check for circular references */
431
432			if (obj_desc == operand) {
433				return_ACPI_STATUS(AE_AML_CIRCULAR_REFERENCE);
434			}
435			break;
436
437		case ACPI_REFCLASS_INDEX:
438
439			/* Get the type of this reference (index into another object) */
440
441			type = obj_desc->reference.target_type;
442			if (type != ACPI_TYPE_PACKAGE) {
443				goto exit;
444			}
445
446			/*
447			 * The main object is a package, we want to get the type
448			 * of the individual package element that is referenced by
449			 * the index.
450			 *
451			 * This could of course in turn be another reference object.
452			 */
453			obj_desc = *(obj_desc->reference.where);
454			if (!obj_desc) {
455
456				/* NULL package elements are allowed */
457
458				type = 0;	/* Uninitialized */
459				goto exit;
460			}
461			break;
462
463		case ACPI_REFCLASS_TABLE:
464
465			type = ACPI_TYPE_DDB_HANDLE;
466			goto exit;
467
468		case ACPI_REFCLASS_LOCAL:
469		case ACPI_REFCLASS_ARG:
470
471			if (return_desc) {
472				status =
473				    acpi_ds_method_data_get_value(obj_desc->
474								  reference.
475								  class,
476								  obj_desc->
477								  reference.
478								  value,
479								  walk_state,
480								  &obj_desc);
481				if (ACPI_FAILURE(status)) {
482					return_ACPI_STATUS(status);
483				}
484				acpi_ut_remove_reference(obj_desc);
485			} else {
486				status =
487				    acpi_ds_method_data_get_node(obj_desc->
488								 reference.
489								 class,
490								 obj_desc->
491								 reference.
492								 value,
493								 walk_state,
494								 &node);
495				if (ACPI_FAILURE(status)) {
496					return_ACPI_STATUS(status);
497				}
498
499				obj_desc = acpi_ns_get_attached_object(node);
500				if (!obj_desc) {
501					type = ACPI_TYPE_ANY;
502					goto exit;
503				}
504			}
505			break;
506
507		case ACPI_REFCLASS_DEBUG:
508
509			/* The Debug Object is of type "DebugObject" */
510
511			type = ACPI_TYPE_DEBUG_OBJECT;
512			goto exit;
513
514		default:
515
516			ACPI_ERROR((AE_INFO,
517				    "Unknown Reference Class 0x%2.2X",
518				    obj_desc->reference.class));
519			return_ACPI_STATUS(AE_AML_INTERNAL);
520		}
521	}
522
523	/*
524	 * Now we are guaranteed to have an object that has not been created
525	 * via the ref_of or Index operators.
526	 */
527	type = obj_desc->common.type;
528
529exit:
530	/* Convert internal types to external types */
531
532	switch (type) {
533	case ACPI_TYPE_LOCAL_REGION_FIELD:
534	case ACPI_TYPE_LOCAL_BANK_FIELD:
535	case ACPI_TYPE_LOCAL_INDEX_FIELD:
536
537		type = ACPI_TYPE_FIELD_UNIT;
538		break;
539
540	case ACPI_TYPE_LOCAL_SCOPE:
541
542		/* Per ACPI Specification, Scope is untyped */
543
544		type = ACPI_TYPE_ANY;
545		break;
546
547	default:
548
549		/* No change to Type required */
550
551		break;
552	}
553
554	*return_type = type;
555	if (return_desc) {
556		*return_desc = obj_desc;
557	}
558	return_ACPI_STATUS(AE_OK);
559}
560