Linux Audio

Check our new training course

Loading...
v3.1
  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
 53ACPI_MODULE_NAME("exresolv")
 54
 55/* Local prototypes */
 56static acpi_status
 57acpi_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
 75acpi_status
 76acpi_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
137static acpi_status
138acpi_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
335acpi_status
336acpi_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}
v4.6
 
  1/******************************************************************************
  2 *
  3 * Module Name: exresolv - AML Interpreter object resolution
  4 *
  5 *****************************************************************************/
  6
  7/*
  8 * Copyright (C) 2000 - 2016, 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 "
221						    "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 = ACPI_CAST_PTR(void, operand);
341	struct acpi_namespace_node *node =
342	    ACPI_CAST_PTR(struct acpi_namespace_node, operand);
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
353		type = obj_desc->common.type;
354		break;
355
356	case ACPI_DESC_TYPE_NAMED:
357
358		type = ((struct acpi_namespace_node *)obj_desc)->type;
359		obj_desc = acpi_ns_get_attached_object(node);
 
 
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 = 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}