exresolv.c 14.1 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8

/******************************************************************************
 *
 * Module Name: exresolv - AML Interpreter object resolution
 *
 *****************************************************************************/

/*
B
Bob Moore 已提交
9
 * Copyright (C) 2000 - 2006, R. Byron Moore
L
Linus Torvalds 已提交
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer,
 *    without modification.
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
 *    substantially similar to the "NO WARRANTY" disclaimer below
 *    ("Disclaimer") and any redistribution must be conditioned upon
 *    including a substantially similar Disclaimer requirement for further
 *    binary redistribution.
 * 3. Neither the names of the above-listed copyright holders nor the names
 *    of any contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * Alternatively, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") version 2 as published by the Free
 * Software Foundation.
 *
 * NO WARRANTY
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 */

#include <acpi/acpi.h>
#include <acpi/amlcode.h>
#include <acpi/acdispat.h>
#include <acpi/acinterp.h>
#include <acpi/acnamesp.h>
#include <acpi/acparser.h>

#define _COMPONENT          ACPI_EXECUTER
L
Len Brown 已提交
53
ACPI_MODULE_NAME("exresolv")
L
Linus Torvalds 已提交
54

R
Robert Moore 已提交
55 56
/* Local prototypes */
static acpi_status
L
Len Brown 已提交
57 58
acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
				struct acpi_walk_state *walk_state);
L
Linus Torvalds 已提交
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75

/*******************************************************************************
 *
 * FUNCTION:    acpi_ex_resolve_to_value
 *
 * PARAMETERS:  **stack_ptr         - Points to entry on obj_stack, which can
 *                                    be either an (union acpi_operand_object *)
 *                                    or an acpi_handle.
 *              walk_state          - Current method state
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Convert Reference objects to values
 *
 ******************************************************************************/

acpi_status
L
Len Brown 已提交
76 77
acpi_ex_resolve_to_value(union acpi_operand_object **stack_ptr,
			 struct acpi_walk_state *walk_state)
L
Linus Torvalds 已提交
78
{
L
Len Brown 已提交
79
	acpi_status status;
L
Linus Torvalds 已提交
80

B
Bob Moore 已提交
81
	ACPI_FUNCTION_TRACE_PTR(ex_resolve_to_value, stack_ptr);
L
Linus Torvalds 已提交
82 83

	if (!stack_ptr || !*stack_ptr) {
B
Bob Moore 已提交
84
		ACPI_ERROR((AE_INFO, "Internal - null pointer"));
L
Len Brown 已提交
85
		return_ACPI_STATUS(AE_AML_NO_OPERAND);
L
Linus Torvalds 已提交
86 87 88 89 90 91 92
	}

	/*
	 * The entity pointed to by the stack_ptr can be either
	 * 1) A valid union acpi_operand_object, or
	 * 2) A struct acpi_namespace_node (named_obj)
	 */
L
Len Brown 已提交
93 94 95 96
	if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_OPERAND) {
		status = acpi_ex_resolve_object_to_value(stack_ptr, walk_state);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
97
		}
R
Robert Moore 已提交
98 99

		if (!*stack_ptr) {
B
Bob Moore 已提交
100
			ACPI_ERROR((AE_INFO, "Internal - null pointer"));
L
Len Brown 已提交
101
			return_ACPI_STATUS(AE_AML_NO_OPERAND);
R
Robert Moore 已提交
102
		}
L
Linus Torvalds 已提交
103 104 105 106 107 108
	}

	/*
	 * Object on the stack may have changed if acpi_ex_resolve_object_to_value()
	 * was called (i.e., we can't use an _else_ here.)
	 */
L
Len Brown 已提交
109 110 111 112 113 114 115
	if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_NAMED) {
		status =
		    acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR
						  (struct acpi_namespace_node,
						   stack_ptr), walk_state);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
116 117 118
		}
	}

L
Len Brown 已提交
119 120
	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Resolved object %p\n", *stack_ptr));
	return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
121 122 123 124 125 126
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ex_resolve_object_to_value
 *
R
Robert Moore 已提交
127
 * PARAMETERS:  stack_ptr       - Pointer to an internal object
L
Linus Torvalds 已提交
128 129 130 131
 *              walk_state      - Current method state
 *
 * RETURN:      Status
 *
R
Robert Moore 已提交
132
 * DESCRIPTION: Retrieve the value from an internal object. The Reference type
L
Linus Torvalds 已提交
133 134 135 136
 *              uses the associated AML opcode to determine the value.
 *
 ******************************************************************************/

R
Robert Moore 已提交
137
static acpi_status
L
Len Brown 已提交
138 139
acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
				struct acpi_walk_state *walk_state)
L
Linus Torvalds 已提交
140
{
L
Len Brown 已提交
141 142 143 144 145
	acpi_status status = AE_OK;
	union acpi_operand_object *stack_desc;
	void *temp_node;
	union acpi_operand_object *obj_desc;
	u16 opcode;
L
Linus Torvalds 已提交
146

B
Bob Moore 已提交
147
	ACPI_FUNCTION_TRACE(ex_resolve_object_to_value);
L
Linus Torvalds 已提交
148 149 150 151 152

	stack_desc = *stack_ptr;

	/* This is an union acpi_operand_object    */

L
Len Brown 已提交
153
	switch (ACPI_GET_OBJECT_TYPE(stack_desc)) {
L
Linus Torvalds 已提交
154 155 156 157 158 159 160 161
	case ACPI_TYPE_LOCAL_REFERENCE:

		opcode = stack_desc->reference.opcode;

		switch (opcode) {
		case AML_NAME_OP:

			/*
R
Robert Moore 已提交
162
			 * Convert name reference to a namespace node
L
Linus Torvalds 已提交
163 164 165 166 167 168
			 * Then, acpi_ex_resolve_node_to_value can be used to get the value
			 */
			temp_node = stack_desc->reference.object;

			/* Delete the Reference Object */

L
Len Brown 已提交
169
			acpi_ut_remove_reference(stack_desc);
L
Linus Torvalds 已提交
170

R
Robert Moore 已提交
171
			/* Return the namespace node */
L
Linus Torvalds 已提交
172 173 174 175 176 177 178 179 180 181 182

			(*stack_ptr) = temp_node;
			break;

		case AML_LOCAL_OP:
		case AML_ARG_OP:

			/*
			 * Get the local from the method's state info
			 * Note: this increments the local's object reference count
			 */
L
Len Brown 已提交
183 184 185 186 187 188 189
			status = acpi_ds_method_data_get_value(opcode,
							       stack_desc->
							       reference.offset,
							       walk_state,
							       &obj_desc);
			if (ACPI_FAILURE(status)) {
				return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
190 191
			}

L
Len Brown 已提交
192
			ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
B
Bob Moore 已提交
193
					  "[Arg/Local %X] ValueObj is %p\n",
L
Len Brown 已提交
194 195
					  stack_desc->reference.offset,
					  obj_desc));
L
Linus Torvalds 已提交
196 197 198 199 200

			/*
			 * Now we can delete the original Reference Object and
			 * replace it with the resolved value
			 */
L
Len Brown 已提交
201
			acpi_ut_remove_reference(stack_desc);
L
Linus Torvalds 已提交
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
			*stack_ptr = obj_desc;
			break;

		case AML_INDEX_OP:

			switch (stack_desc->reference.target_type) {
			case ACPI_TYPE_BUFFER_FIELD:

				/* Just return - leave the Reference on the stack */
				break;

			case ACPI_TYPE_PACKAGE:

				obj_desc = *stack_desc->reference.where;
				if (obj_desc) {
					/*
					 * Valid obj descriptor, copy pointer to return value
					 * (i.e., dereference the package index)
					 * Delete the ref object, increment the returned object
					 */
L
Len Brown 已提交
222 223
					acpi_ut_remove_reference(stack_desc);
					acpi_ut_add_reference(obj_desc);
L
Linus Torvalds 已提交
224
					*stack_ptr = obj_desc;
L
Len Brown 已提交
225
				} else {
L
Linus Torvalds 已提交
226 227 228 229
					/*
					 * A NULL object descriptor means an unitialized element of
					 * the package, can't dereference it
					 */
B
Bob Moore 已提交
230 231 232
					ACPI_ERROR((AE_INFO,
						    "Attempt to deref an Index to NULL pkg element Idx=%p",
						    stack_desc));
L
Linus Torvalds 已提交
233 234 235 236 237 238 239 240
					status = AE_AML_UNINITIALIZED_ELEMENT;
				}
				break;

			default:

				/* Invalid reference object */

B
Bob Moore 已提交
241
				ACPI_ERROR((AE_INFO,
B
Bob Moore 已提交
242
					    "Unknown TargetType %X in Index/Reference obj %p",
B
Bob Moore 已提交
243 244
					    stack_desc->reference.target_type,
					    stack_desc));
L
Linus Torvalds 已提交
245 246 247 248 249 250 251 252 253 254 255 256 257
				status = AE_AML_INTERNAL;
				break;
			}
			break;

		case AML_REF_OF_OP:
		case AML_DEBUG_OP:
		case AML_LOAD_OP:

			/* Just leave the object as-is */

			break;

L
Len Brown 已提交
258
		case AML_INT_NAMEPATH_OP:	/* Reference to a named object */
R
Robert Moore 已提交
259 260 261 262

			/* Get the object pointed to by the namespace node */

			*stack_ptr = (stack_desc->reference.node)->object;
L
Len Brown 已提交
263 264
			acpi_ut_add_reference(*stack_ptr);
			acpi_ut_remove_reference(stack_desc);
R
Robert Moore 已提交
265
			break;
L
Linus Torvalds 已提交
266 267 268

		default:

B
Bob Moore 已提交
269 270 271 272
			ACPI_ERROR((AE_INFO,
				    "Unknown Reference opcode %X (%s) in %p",
				    opcode, acpi_ps_get_opcode_name(opcode),
				    stack_desc));
L
Linus Torvalds 已提交
273 274 275 276 277 278 279
			status = AE_AML_INTERNAL;
			break;
		}
		break;

	case ACPI_TYPE_BUFFER:

L
Len Brown 已提交
280
		status = acpi_ds_get_buffer_arguments(stack_desc);
L
Linus Torvalds 已提交
281 282 283 284
		break;

	case ACPI_TYPE_PACKAGE:

L
Len Brown 已提交
285
		status = acpi_ds_get_package_arguments(stack_desc);
L
Linus Torvalds 已提交
286 287
		break;

L
Len Brown 已提交
288
		/* These cases may never happen here, but just in case.. */
R
Robert Moore 已提交
289

L
Linus Torvalds 已提交
290 291 292 293 294
	case ACPI_TYPE_BUFFER_FIELD:
	case ACPI_TYPE_LOCAL_REGION_FIELD:
	case ACPI_TYPE_LOCAL_BANK_FIELD:
	case ACPI_TYPE_LOCAL_INDEX_FIELD:

L
Len Brown 已提交
295
		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
B
Bob Moore 已提交
296
				  "FieldRead SourceDesc=%p Type=%X\n",
L
Len Brown 已提交
297 298
				  stack_desc,
				  ACPI_GET_OBJECT_TYPE(stack_desc)));
L
Linus Torvalds 已提交
299

L
Len Brown 已提交
300 301 302 303
		status =
		    acpi_ex_read_data_from_field(walk_state, stack_desc,
						 &obj_desc);
		*stack_ptr = (void *)obj_desc;
L
Linus Torvalds 已提交
304 305 306 307 308 309
		break;

	default:
		break;
	}

L
Len Brown 已提交
310
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ex_resolve_multiple
 *
 * PARAMETERS:  walk_state          - Current state (contains AML opcode)
 *              Operand             - Starting point for resolution
 *              return_type         - Where the object type is returned
 *              return_desc         - Where the resolved object is returned
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Return the base object and type.  Traverse a reference list if
 *              necessary to get to the base object.
 *
 ******************************************************************************/

acpi_status
L
Len Brown 已提交
330 331 332 333
acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
			 union acpi_operand_object *operand,
			 acpi_object_type * return_type,
			 union acpi_operand_object **return_desc)
L
Linus Torvalds 已提交
334
{
L
Len Brown 已提交
335 336 337 338
	union acpi_operand_object *obj_desc = (void *)operand;
	struct acpi_namespace_node *node;
	acpi_object_type type;
	acpi_status status;
L
Linus Torvalds 已提交
339

B
Bob Moore 已提交
340
	ACPI_FUNCTION_TRACE(acpi_ex_resolve_multiple);
L
Linus Torvalds 已提交
341

R
Robert Moore 已提交
342 343
	/* Operand can be either a namespace node or an operand descriptor */

L
Len Brown 已提交
344
	switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
L
Linus Torvalds 已提交
345 346 347 348 349
	case ACPI_DESC_TYPE_OPERAND:
		type = obj_desc->common.type;
		break;

	case ACPI_DESC_TYPE_NAMED:
L
Len Brown 已提交
350 351 352 353
		type = ((struct acpi_namespace_node *)obj_desc)->type;
		obj_desc =
		    acpi_ns_get_attached_object((struct acpi_namespace_node *)
						obj_desc);
L
Linus Torvalds 已提交
354 355 356 357

		/* If we had an Alias node, use the attached object for type info */

		if (type == ACPI_TYPE_LOCAL_ALIAS) {
L
Len Brown 已提交
358 359 360 361 362
			type = ((struct acpi_namespace_node *)obj_desc)->type;
			obj_desc =
			    acpi_ns_get_attached_object((struct
							 acpi_namespace_node *)
							obj_desc);
L
Linus Torvalds 已提交
363 364 365 366
		}
		break;

	default:
L
Len Brown 已提交
367
		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
L
Linus Torvalds 已提交
368 369
	}

R
Robert Moore 已提交
370
	/* If type is anything other than a reference, we are done */
L
Linus Torvalds 已提交
371 372 373 374 375 376 377 378 379 380 381

	if (type != ACPI_TYPE_LOCAL_REFERENCE) {
		goto exit;
	}

	/*
	 * For reference objects created via the ref_of or Index operators,
	 * we need to get to the base object (as per the ACPI specification
	 * of the object_type and size_of operators). This means traversing
	 * the list of possibly many nested references.
	 */
L
Len Brown 已提交
382
	while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) {
L
Linus Torvalds 已提交
383 384
		switch (obj_desc->reference.opcode) {
		case AML_REF_OF_OP:
B
Bob Moore 已提交
385
		case AML_INT_NAMEPATH_OP:
L
Linus Torvalds 已提交
386 387 388

			/* Dereference the reference pointer */

B
Bob Moore 已提交
389 390 391 392 393 394
			if (obj_desc->reference.opcode == AML_REF_OF_OP) {
				node = obj_desc->reference.object;
			} else {	/* AML_INT_NAMEPATH_OP */

				node = obj_desc->reference.node;
			}
L
Linus Torvalds 已提交
395 396 397

			/* All "References" point to a NS node */

L
Len Brown 已提交
398 399
			if (ACPI_GET_DESCRIPTOR_TYPE(node) !=
			    ACPI_DESC_TYPE_NAMED) {
B
Bob Moore 已提交
400 401 402
				ACPI_ERROR((AE_INFO, "Not a NS node %p [%s]",
					    node,
					    acpi_ut_get_descriptor_name(node)));
L
Len Brown 已提交
403
				return_ACPI_STATUS(AE_AML_INTERNAL);
L
Linus Torvalds 已提交
404 405 406 407
			}

			/* Get the attached object */

L
Len Brown 已提交
408
			obj_desc = acpi_ns_get_attached_object(node);
L
Linus Torvalds 已提交
409
			if (!obj_desc) {
B
Bob Moore 已提交
410

L
Linus Torvalds 已提交
411 412
				/* No object, use the NS node type */

L
Len Brown 已提交
413
				type = acpi_ns_get_type(node);
L
Linus Torvalds 已提交
414 415 416 417 418 419
				goto exit;
			}

			/* Check for circular references */

			if (obj_desc == operand) {
L
Len Brown 已提交
420
				return_ACPI_STATUS(AE_AML_CIRCULAR_REFERENCE);
L
Linus Torvalds 已提交
421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
			}
			break;

		case AML_INDEX_OP:

			/* Get the type of this reference (index into another object) */

			type = obj_desc->reference.target_type;
			if (type != ACPI_TYPE_PACKAGE) {
				goto exit;
			}

			/*
			 * The main object is a package, we want to get the type
			 * of the individual package element that is referenced by
			 * the index.
			 *
			 * This could of course in turn be another reference object.
			 */
			obj_desc = *(obj_desc->reference.where);
			if (!obj_desc) {
B
Bob Moore 已提交
442

L
Linus Torvalds 已提交
443 444
				/* NULL package elements are allowed */

L
Len Brown 已提交
445
				type = 0;	/* Uninitialized */
L
Linus Torvalds 已提交
446 447 448 449 450 451 452 453
				goto exit;
			}
			break;

		case AML_LOCAL_OP:
		case AML_ARG_OP:

			if (return_desc) {
L
Len Brown 已提交
454 455 456 457 458 459 460 461 462 463 464
				status =
				    acpi_ds_method_data_get_value(obj_desc->
								  reference.
								  opcode,
								  obj_desc->
								  reference.
								  offset,
								  walk_state,
								  &obj_desc);
				if (ACPI_FAILURE(status)) {
					return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
465
				}
L
Len Brown 已提交
466 467 468 469 470 471 472 473 474 475 476 477 478
				acpi_ut_remove_reference(obj_desc);
			} else {
				status =
				    acpi_ds_method_data_get_node(obj_desc->
								 reference.
								 opcode,
								 obj_desc->
								 reference.
								 offset,
								 walk_state,
								 &node);
				if (ACPI_FAILURE(status)) {
					return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
479 480
				}

L
Len Brown 已提交
481
				obj_desc = acpi_ns_get_attached_object(node);
L
Linus Torvalds 已提交
482 483 484 485 486 487 488 489 490
				if (!obj_desc) {
					type = ACPI_TYPE_ANY;
					goto exit;
				}
			}
			break;

		case AML_DEBUG_OP:

B
Bob Moore 已提交
491
			/* The Debug Object is of type "DebugObject" */
L
Linus Torvalds 已提交
492 493 494 495 496 497

			type = ACPI_TYPE_DEBUG_OBJECT;
			goto exit;

		default:

B
Bob Moore 已提交
498 499 500
			ACPI_ERROR((AE_INFO,
				    "Unknown Reference subtype %X",
				    obj_desc->reference.opcode));
L
Len Brown 已提交
501
			return_ACPI_STATUS(AE_AML_INTERNAL);
L
Linus Torvalds 已提交
502 503 504 505 506 507 508
		}
	}

	/*
	 * Now we are guaranteed to have an object that has not been created
	 * via the ref_of or Index operators.
	 */
L
Len Brown 已提交
509
	type = ACPI_GET_OBJECT_TYPE(obj_desc);
L
Linus Torvalds 已提交
510

L
Len Brown 已提交
511
      exit:
L
Linus Torvalds 已提交
512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537
	/* Convert internal types to external types */

	switch (type) {
	case ACPI_TYPE_LOCAL_REGION_FIELD:
	case ACPI_TYPE_LOCAL_BANK_FIELD:
	case ACPI_TYPE_LOCAL_INDEX_FIELD:

		type = ACPI_TYPE_FIELD_UNIT;
		break;

	case ACPI_TYPE_LOCAL_SCOPE:

		/* Per ACPI Specification, Scope is untyped */

		type = ACPI_TYPE_ANY;
		break;

	default:
		/* No change to Type required */
		break;
	}

	*return_type = type;
	if (return_desc) {
		*return_desc = obj_desc;
	}
L
Len Brown 已提交
538
	return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
539
}