Example #1
0
acpi_status acpi_ex_opcode_1A_1T_0R(struct acpi_walk_state *walk_state)
{
	acpi_status status = AE_OK;
	union acpi_operand_object **operand = &walk_state->operands[0];

	ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_1T_0R,
				acpi_ps_get_opcode_name(walk_state->opcode));

	/* Examine the AML opcode */

	switch (walk_state->opcode) {
	case AML_LOAD_OP:

		status = acpi_ex_load_op(operand[0], operand[1], walk_state);
		break;

	default:		/* Unknown opcode */

		ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
			    walk_state->opcode));
		status = AE_AML_BAD_OPCODE;
		goto cleanup;
	}

      cleanup:

	return_ACPI_STATUS(status);
}
Example #2
0
acpi_status
acpi_ex_opcode_2A_0T_0R (
	acpi_walk_state         *walk_state)
{
	acpi_operand_object     **operand = &walk_state->operands[0];
	acpi_namespace_node     *node;
	acpi_status             status = AE_OK;


	FUNCTION_TRACE_STR ("Ex_opcode_2A_0T_0R", acpi_ps_get_opcode_name (walk_state->opcode));


	/* Examine the opcode */

	switch (walk_state->opcode) {

	case AML_NOTIFY_OP:         /* Notify (Notify_object, Notify_value) */

		/* The first operand is a namespace node */

		node = (acpi_namespace_node *) operand[0];

		/* The node must refer to a device or thermal zone */

		if (node && operand[1])     /* TBD: is this check necessary? */ {
			switch (node->type) {
			case ACPI_TYPE_DEVICE:
			case ACPI_TYPE_THERMAL:

				/*
				 * Dispatch the notify to the appropriate handler
				 * NOTE: the request is queued for execution after this method
				 * completes.  The notify handlers are NOT invoked synchronously
				 * from this thread -- because handlers may in turn run other
				 * control methods.
				 */
				status = acpi_ev_queue_notify_request (node,
						 (u32) operand[1]->integer.value);
				break;

			default:
				ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unexpected notify object type %X\n",
					node->type));

				status = AE_AML_OPERAND_TYPE;
				break;
			}
		}
		break;

	default:

		REPORT_ERROR (("Acpi_ex_opcode_2A_0T_0R: Unknown opcode %X\n", walk_state->opcode));
		status = AE_AML_BAD_OPCODE;
	}

	return_ACPI_STATUS (status);
}
Example #3
0
acpi_status acpi_ex_opcode_1A_0T_0R(struct acpi_walk_state *walk_state)
{
	union acpi_operand_object **operand = &walk_state->operands[0];
	acpi_status status = AE_OK;

	ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_0T_0R,
				acpi_ps_get_opcode_name(walk_state->opcode));

	/* Examine the AML opcode */

	switch (walk_state->opcode) {
	case AML_RELEASE_OP:	/*  Release (mutex_object) */

		status = acpi_ex_release_mutex(operand[0], walk_state);
		break;

	case AML_RESET_OP:	/*  Reset (event_object) */

		status = acpi_ex_system_reset_event(operand[0]);
		break;

	case AML_SIGNAL_OP:	/*  Signal (event_object) */

		status = acpi_ex_system_signal_event(operand[0]);
		break;

	case AML_SLEEP_OP:	/*  Sleep (msec_time) */

		status = acpi_ex_system_do_suspend(operand[0]->integer.value);
		break;

	case AML_STALL_OP:	/*  Stall (usec_time) */

		status =
		    acpi_ex_system_do_stall((u32) operand[0]->integer.value);
		break;

	case AML_UNLOAD_OP:	/*  Unload (Handle) */

		status = acpi_ex_unload_table(operand[0]);
		break;

	default:		/*  Unknown opcode  */

		ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
			    walk_state->opcode));
		status = AE_AML_BAD_OPCODE;
		break;
	}

	return_ACPI_STATUS(status);
}
Example #4
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_ex_opcode_0A_0T_1R
 *
 * PARAMETERS:  walk_state          - Current state (contains AML opcode)
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Execute operator with no operands, one return value
 *
 ******************************************************************************/
acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state)
{
	acpi_status status = AE_OK;
	union acpi_operand_object *return_desc = NULL;

	ACPI_FUNCTION_TRACE_STR(ex_opcode_0A_0T_1R,
				acpi_ps_get_opcode_name(walk_state->opcode));

	/* Examine the AML opcode */

	switch (walk_state->opcode) {
	case AML_TIMER_OP:	/*  Timer () */

		/* Create a return object of type Integer */

		return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
		if (!return_desc) {
			status = AE_NO_MEMORY;
			goto cleanup;
		}
#if ACPI_MACHINE_WIDTH != 16
		return_desc->integer.value = acpi_os_get_timer();
#endif
		break;

	default:		/*  Unknown opcode  */

		ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
			    walk_state->opcode));
		status = AE_AML_BAD_OPCODE;
		break;
	}

      cleanup:

	/* Delete return object on error */

	if ((ACPI_FAILURE(status)) || walk_state->result_obj) {
		acpi_ut_remove_reference(return_desc);
	} else {
		/* Save the return value */

		walk_state->result_obj = return_desc;
	}

	return_ACPI_STATUS(status);
}
/*******************************************************************************
 *
 * FUNCTION:    acpi_ex_opcode_3A_0T_0R
 *
 * PARAMETERS:  walk_state          - Current walk state
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Execute Triadic operator (3 operands)
 *
 ******************************************************************************/
acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state)
{
	union acpi_operand_object **operand = &walk_state->operands[0];
	struct acpi_signal_fatal_info *fatal;
	acpi_status status = AE_OK;

	ACPI_FUNCTION_TRACE_STR("ex_opcode_3A_0T_0R",
				acpi_ps_get_opcode_name(walk_state->opcode));

	switch (walk_state->opcode) {
	case AML_FATAL_OP:	/* Fatal (fatal_type fatal_code fatal_arg) */

		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				  "fatal_op: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
				  (u32) operand[0]->integer.value,
				  (u32) operand[1]->integer.value,
				  (u32) operand[2]->integer.value));

		fatal =
		    ACPI_MEM_ALLOCATE(sizeof(struct acpi_signal_fatal_info));
		if (fatal) {
			fatal->type = (u32) operand[0]->integer.value;
			fatal->code = (u32) operand[1]->integer.value;
			fatal->argument = (u32) operand[2]->integer.value;
		}

		/* Always signal the OS! */

		status = acpi_os_signal(ACPI_SIGNAL_FATAL, fatal);

		/* Might return while OS is shutting down, just continue */

		ACPI_MEM_FREE(fatal);
		break;

	default:

		ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
			    walk_state->opcode));
		status = AE_AML_BAD_OPCODE;
		goto cleanup;
	}

      cleanup:

	return_ACPI_STATUS(status);
}
Example #6
0
acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state)
{
	union acpi_operand_object **operand = &walk_state->operands[0];
	struct acpi_signal_fatal_info *fatal;
	acpi_status status = AE_OK;

	ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_0T_0R,
				acpi_ps_get_opcode_name(walk_state->opcode));

	switch (walk_state->opcode) {
	case AML_FATAL_OP:	

		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				  "FatalOp: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
				  (u32) operand[0]->integer.value,
				  (u32) operand[1]->integer.value,
				  (u32) operand[2]->integer.value));

		fatal = ACPI_ALLOCATE(sizeof(struct acpi_signal_fatal_info));
		if (fatal) {
			fatal->type = (u32) operand[0]->integer.value;
			fatal->code = (u32) operand[1]->integer.value;
			fatal->argument = (u32) operand[2]->integer.value;
		}

		

		status = acpi_os_signal(ACPI_SIGNAL_FATAL, fatal);

		

		ACPI_FREE(fatal);
		break;

	default:

		ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
			    walk_state->opcode));
		status = AE_AML_BAD_OPCODE;
		goto cleanup;
	}

      cleanup:

	return_ACPI_STATUS(status);
}
acpi_status
acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state,
				 union acpi_parse_object *op)
{
	acpi_status status;
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *operand_desc;
	struct acpi_namespace_node *node;
	union acpi_parse_object *next_op;
	union acpi_parse_object *arg;

	ACPI_FUNCTION_TRACE_PTR(ds_eval_bank_field_operands, op);

	/*
	 * This is where we evaluate the bank_value field of the
	 * bank_field declaration
	 */

	/* next_op points to the op that holds the Region */

	next_op = op->common.value.arg;

	/* next_op points to the op that holds the Bank Register */

	next_op = next_op->common.next;

	/* next_op points to the op that holds the Bank Value */

	next_op = next_op->common.next;

	/*
	 * Set proper index into operand stack for acpi_ds_obj_stack_push
	 * invoked inside acpi_ds_create_operand.
	 *
	 * We use walk_state->Operands[0] to store the evaluated bank_value
	 */
	walk_state->operand_index = 0;

	status = acpi_ds_create_operand(walk_state, next_op, 0);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	status = acpi_ex_resolve_to_value(&walk_state->operands[0], walk_state);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS,
			   acpi_ps_get_opcode_name(op->common.aml_opcode), 1);
	/*
	 * Get the bank_value operand and save it
	 * (at Top of stack)
	 */
	operand_desc = walk_state->operands[0];

	/* Arg points to the start Bank Field */

	arg = acpi_ps_get_arg(op, 4);
	while (arg) {

		/* Ignore OFFSET and ACCESSAS terms here */

		if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
			node = arg->common.node;

			obj_desc = acpi_ns_get_attached_object(node);
			if (!obj_desc) {
				return_ACPI_STATUS(AE_NOT_EXIST);
			}

			obj_desc->bank_field.value =
			    (u32) operand_desc->integer.value;
		}

		/* Move to next field in the list */

		arg = arg->common.next;
	}

	acpi_ut_remove_reference(operand_desc);
	return_ACPI_STATUS(status);
}
Example #8
0
acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state)
{
	union acpi_operand_object **operand = &walk_state->operands[0];
	union acpi_operand_object *return_desc = NULL;
	char *buffer = NULL;
	acpi_status status = AE_OK;
	u64 index;
	acpi_size length;

	ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_1T_1R,
				acpi_ps_get_opcode_name(walk_state->opcode));

	switch (walk_state->opcode) {
	case AML_MID_OP:	/* Mid (Source[0], Index[1], Length[2], Result[3]) */

		/*
		 * Create the return object. The Source operand is guaranteed to be
		 * either a String or a Buffer, so just use its type.
		 */
		return_desc = acpi_ut_create_internal_object((operand[0])->
							     common.type);
		if (!return_desc) {
			status = AE_NO_MEMORY;
			goto cleanup;
		}

		/* Get the Integer values from the objects */

		index = operand[1]->integer.value;
		length = (acpi_size) operand[2]->integer.value;

		/*
		 * If the index is beyond the length of the String/Buffer, or if the
		 * requested length is zero, return a zero-length String/Buffer
		 */
		if (index >= operand[0]->string.length) {
			length = 0;
		}

		/* Truncate request if larger than the actual String/Buffer */

		else if ((index + length) > operand[0]->string.length) {
			length = (acpi_size) operand[0]->string.length -
			    (acpi_size) index;
		}

		/* Strings always have a sub-pointer, not so for buffers */

		switch ((operand[0])->common.type) {
		case ACPI_TYPE_STRING:

			/* Always allocate a new buffer for the String */

			buffer = ACPI_ALLOCATE_ZEROED((acpi_size) length + 1);
			if (!buffer) {
				status = AE_NO_MEMORY;
				goto cleanup;
			}
			break;

		case ACPI_TYPE_BUFFER:

			/* If the requested length is zero, don't allocate a buffer */

			if (length > 0) {

				/* Allocate a new buffer for the Buffer */

				buffer = ACPI_ALLOCATE_ZEROED(length);
				if (!buffer) {
					status = AE_NO_MEMORY;
					goto cleanup;
				}
			}
			break;

		default:	/* Should not happen */

			status = AE_AML_OPERAND_TYPE;
			goto cleanup;
		}

		if (buffer) {

			/* We have a buffer, copy the portion requested */

			ACPI_MEMCPY(buffer, operand[0]->string.pointer + index,
				    length);
		}

		/* Set the length of the new String/Buffer */

		return_desc->string.pointer = buffer;
		return_desc->string.length = (u32) length;

		/* Mark buffer initialized */

		return_desc->buffer.flags |= AOPOBJ_DATA_VALID;
		break;

	default:

		ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
			    walk_state->opcode));
		status = AE_AML_BAD_OPCODE;
		goto cleanup;
	}

	/* Store the result in the target */

	status = acpi_ex_store(return_desc, operand[3], walk_state);

      cleanup:

	/* Delete return object on error */

	if (ACPI_FAILURE(status) || walk_state->result_obj) {
		acpi_ut_remove_reference(return_desc);
		walk_state->result_obj = NULL;
	}

	/* Set the return object and exit */

	else {
		walk_state->result_obj = return_desc;
	}
	return_ACPI_STATUS(status);
}
static acpi_status
acpi_ds_init_buffer_field(u16 aml_opcode,
			  union acpi_operand_object *obj_desc,
			  union acpi_operand_object *buffer_desc,
			  union acpi_operand_object *offset_desc,
			  union acpi_operand_object *length_desc,
			  union acpi_operand_object *result_desc)
{
	u32 offset;
	u32 bit_offset;
	u32 bit_count;
	u8 field_flags;
	acpi_status status;

	ACPI_FUNCTION_TRACE_PTR(ds_init_buffer_field, obj_desc);

	/* Host object must be a Buffer */

	if (buffer_desc->common.type != ACPI_TYPE_BUFFER) {
		ACPI_ERROR((AE_INFO,
			    "Target of Create Field is not a Buffer object - %s",
			    acpi_ut_get_object_type_name(buffer_desc)));

		status = AE_AML_OPERAND_TYPE;
		goto cleanup;
	}

	/*
	 * The last parameter to all of these opcodes (result_desc) started
	 * out as a name_string, and should therefore now be a NS node
	 * after resolution in acpi_ex_resolve_operands().
	 */
	if (ACPI_GET_DESCRIPTOR_TYPE(result_desc) != ACPI_DESC_TYPE_NAMED) {
		ACPI_ERROR((AE_INFO,
			    "(%s) destination not a NS Node [%s]",
			    acpi_ps_get_opcode_name(aml_opcode),
			    acpi_ut_get_descriptor_name(result_desc)));

		status = AE_AML_OPERAND_TYPE;
		goto cleanup;
	}

	offset = (u32) offset_desc->integer.value;

	/*
	 * Setup the Bit offsets and counts, according to the opcode
	 */
	switch (aml_opcode) {
	case AML_CREATE_FIELD_OP:

		/* Offset is in bits, count is in bits */

		field_flags = AML_FIELD_ACCESS_BYTE;
		bit_offset = offset;
		bit_count = (u32) length_desc->integer.value;

		/* Must have a valid (>0) bit count */

		if (bit_count == 0) {
			ACPI_ERROR((AE_INFO,
				    "Attempt to CreateField of length zero"));
			status = AE_AML_OPERAND_VALUE;
			goto cleanup;
		}
		break;

	case AML_CREATE_BIT_FIELD_OP:

		/* Offset is in bits, Field is one bit */

		bit_offset = offset;
		bit_count = 1;
		field_flags = AML_FIELD_ACCESS_BYTE;
		break;

	case AML_CREATE_BYTE_FIELD_OP:

		/* Offset is in bytes, field is one byte */

		bit_offset = 8 * offset;
		bit_count = 8;
		field_flags = AML_FIELD_ACCESS_BYTE;
		break;

	case AML_CREATE_WORD_FIELD_OP:

		/* Offset is in bytes, field is one word */

		bit_offset = 8 * offset;
		bit_count = 16;
		field_flags = AML_FIELD_ACCESS_WORD;
		break;

	case AML_CREATE_DWORD_FIELD_OP:

		/* Offset is in bytes, field is one dword */

		bit_offset = 8 * offset;
		bit_count = 32;
		field_flags = AML_FIELD_ACCESS_DWORD;
		break;

	case AML_CREATE_QWORD_FIELD_OP:

		/* Offset is in bytes, field is one qword */

		bit_offset = 8 * offset;
		bit_count = 64;
		field_flags = AML_FIELD_ACCESS_QWORD;
		break;

	default:

		ACPI_ERROR((AE_INFO,
			    "Unknown field creation opcode 0x%02X",
			    aml_opcode));
		status = AE_AML_BAD_OPCODE;
		goto cleanup;
	}

	/* Entire field must fit within the current length of the buffer */

	if ((bit_offset + bit_count) > (8 * (u32) buffer_desc->buffer.length)) {
		ACPI_ERROR((AE_INFO,
			    "Field [%4.4s] at %u exceeds Buffer [%4.4s] size %u (bits)",
			    acpi_ut_get_node_name(result_desc),
			    bit_offset + bit_count,
			    acpi_ut_get_node_name(buffer_desc->buffer.node),
			    8 * (u32) buffer_desc->buffer.length));
		status = AE_AML_BUFFER_LIMIT;
		goto cleanup;
	}

	/*
	 * Initialize areas of the field object that are common to all fields
	 * For field_flags, use LOCK_RULE = 0 (NO_LOCK),
	 * UPDATE_RULE = 0 (UPDATE_PRESERVE)
	 */
	status = acpi_ex_prep_common_field_object(obj_desc, field_flags, 0,
						  bit_offset, bit_count);
	if (ACPI_FAILURE(status)) {
		goto cleanup;
	}

	obj_desc->buffer_field.buffer_obj = buffer_desc;

	/* Reference count for buffer_desc inherits obj_desc count */

	buffer_desc->common.reference_count = (u16)
	    (buffer_desc->common.reference_count +
	     obj_desc->common.reference_count);

cleanup:

	/* Always delete the operands */

	acpi_ut_remove_reference(offset_desc);
	acpi_ut_remove_reference(buffer_desc);

	if (aml_opcode == AML_CREATE_FIELD_OP) {
		acpi_ut_remove_reference(length_desc);
	}

	/* On failure, delete the result descriptor */

	if (ACPI_FAILURE(status)) {
		acpi_ut_remove_reference(result_desc);	/* Result descriptor */
	} else {
		/* Now the address and length are valid for this buffer_field */

		obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID;
	}

	return_ACPI_STATUS(status);
}
acpi_status
acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,
				   union acpi_parse_object *op)
{
	acpi_status status;
	union acpi_operand_object *obj_desc;
	struct acpi_namespace_node *node;
	union acpi_parse_object *next_op;

	ACPI_FUNCTION_TRACE_PTR(ds_eval_buffer_field_operands, op);

	/*
	 * This is where we evaluate the address and length fields of the
	 * create_xxx_field declaration
	 */
	node = op->common.node;

	/* next_op points to the op that holds the Buffer */

	next_op = op->common.value.arg;

	/* Evaluate/create the address and length operands */

	status = acpi_ds_create_operands(walk_state, next_op);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	obj_desc = acpi_ns_get_attached_object(node);
	if (!obj_desc) {
		return_ACPI_STATUS(AE_NOT_EXIST);
	}

	/* Resolve the operands */

	status = acpi_ex_resolve_operands(op->common.aml_opcode,
					  ACPI_WALK_OPERANDS, walk_state);
	if (ACPI_FAILURE(status)) {
		ACPI_ERROR((AE_INFO, "(%s) bad operand(s), status 0x%X",
			    acpi_ps_get_opcode_name(op->common.aml_opcode),
			    status));

		return_ACPI_STATUS(status);
	}

	/* Initialize the Buffer Field */

	if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {

		/* NOTE: Slightly different operands for this opcode */

		status =
		    acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc,
					      walk_state->operands[0],
					      walk_state->operands[1],
					      walk_state->operands[2],
					      walk_state->operands[3]);
	} else {
		/* All other, create_xxx_field opcodes */

		status =
		    acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc,
					      walk_state->operands[0],
					      walk_state->operands[1], NULL,
					      walk_state->operands[2]);
	}

	return_ACPI_STATUS(status);
}
Example #11
0
acpi_status
acpi_ex_opcode_2A_2T_1R (
	acpi_walk_state         *walk_state)
{
	acpi_operand_object     **operand = &walk_state->operands[0];
	acpi_operand_object     *return_desc1 = NULL;
	acpi_operand_object     *return_desc2 = NULL;
	acpi_status             status;


	FUNCTION_TRACE_STR ("Ex_opcode_2A_2T_1R", acpi_ps_get_opcode_name (walk_state->opcode));


	/*
	 * Execute the opcode
	 */
	switch (walk_state->opcode) {
	case AML_DIVIDE_OP:             /* Divide (Dividend, Divisor, Remainder_result Quotient_result) */

		return_desc1 = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
		if (!return_desc1) {
			status = AE_NO_MEMORY;
			goto cleanup;
		}

		return_desc2 = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
		if (!return_desc2) {
			status = AE_NO_MEMORY;
			goto cleanup;
		}

		/* Quotient to Return_desc1, remainder to Return_desc2 */

		status = acpi_ut_divide (&operand[0]->integer.value, &operand[1]->integer.value,
				   &return_desc1->integer.value, &return_desc2->integer.value);
		if (ACPI_FAILURE (status)) {
			goto cleanup;
		}
		break;


	default:

		REPORT_ERROR (("Acpi_ex_opcode_2A_2T_1R: Unknown opcode %X\n",
				walk_state->opcode));
		status = AE_AML_BAD_OPCODE;
		goto cleanup;
		break;
	}


	/* Store the results to the target reference operands */

	status = acpi_ex_store (return_desc2, operand[2], walk_state);
	if (ACPI_FAILURE (status)) {
		goto cleanup;
	}

	status = acpi_ex_store (return_desc1, operand[3], walk_state);
	if (ACPI_FAILURE (status)) {
		goto cleanup;
	}

	/* Return the remainder */

	walk_state->result_obj = return_desc1;


cleanup:
	/*
	 * Since the remainder is not returned indirectly, remove a reference to
	 * it. Only the quotient is returned indirectly.
	 */
	acpi_ut_remove_reference (return_desc2);

	if (ACPI_FAILURE (status)) {
		/* Delete the return object */

		acpi_ut_remove_reference (return_desc1);
	}

	return_ACPI_STATUS (status);
}
acpi_status
acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
			     union acpi_parse_object *op)
{
	acpi_status status;
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *operand_desc;
	struct acpi_namespace_node *node;
	union acpi_parse_object *next_op;

	ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op);

	/*
	 * This is where we evaluate the address and length fields of the
	 * op_region declaration
	 */
	node = op->common.node;

	/* next_op points to the op that holds the space_iD */

	next_op = op->common.value.arg;

	/* next_op points to address op */

	next_op = next_op->common.next;

	/* Evaluate/create the address and length operands */

	status = acpi_ds_create_operands(walk_state, next_op);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Resolve the length and address operands to numbers */

	status = acpi_ex_resolve_operands(op->common.aml_opcode,
					  ACPI_WALK_OPERANDS, walk_state);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
			   acpi_ps_get_opcode_name(op->common.aml_opcode),
			   1, "after AcpiExResolveOperands");

	obj_desc = acpi_ns_get_attached_object(node);
	if (!obj_desc) {
		return_ACPI_STATUS(AE_NOT_EXIST);
	}

	/*
	 * Get the length operand and save it
	 * (at Top of stack)
	 */
	operand_desc = walk_state->operands[walk_state->num_operands - 1];

	obj_desc->region.length = (u32) operand_desc->integer.value;
	acpi_ut_remove_reference(operand_desc);

	/*
	 * Get the address and save it
	 * (at top of stack - 1)
	 */
	operand_desc = walk_state->operands[walk_state->num_operands - 2];

	obj_desc->region.address = (acpi_physical_address)
	    operand_desc->integer.value;
	acpi_ut_remove_reference(operand_desc);

	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
			  obj_desc,
			  ACPI_FORMAT_UINT64(obj_desc->region.address),
			  obj_desc->region.length));

	/* Now the address and length are valid for this opregion */

	obj_desc->region.flags |= AOPOBJ_DATA_VALID;

	return_ACPI_STATUS(status);
}
Example #13
0
acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state)
{
	union acpi_operand_object **operand = &walk_state->operands[0];
	union acpi_operand_object *return_desc = NULL;
	char *buffer = NULL;
	acpi_status status = AE_OK;
	acpi_integer index;
	acpi_size length;

	ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_1T_1R,
				acpi_ps_get_opcode_name(walk_state->opcode));

	switch (walk_state->opcode) {
	case AML_MID_OP:	

		
		return_desc = acpi_ut_create_internal_object((operand[0])->
							     common.type);
		if (!return_desc) {
			status = AE_NO_MEMORY;
			goto cleanup;
		}

		

		index = operand[1]->integer.value;
		length = (acpi_size) operand[2]->integer.value;

		
		if (index >= operand[0]->string.length) {
			length = 0;
		}

		

		else if ((index + length) > operand[0]->string.length) {
			length = (acpi_size) operand[0]->string.length -
			    (acpi_size) index;
		}

		

		switch ((operand[0])->common.type) {
		case ACPI_TYPE_STRING:

			

			buffer = ACPI_ALLOCATE_ZEROED((acpi_size) length + 1);
			if (!buffer) {
				status = AE_NO_MEMORY;
				goto cleanup;
			}
			break;

		case ACPI_TYPE_BUFFER:

			

			if (length > 0) {

				

				buffer = ACPI_ALLOCATE_ZEROED(length);
				if (!buffer) {
					status = AE_NO_MEMORY;
					goto cleanup;
				}
			}
			break;

		default:	

			status = AE_AML_OPERAND_TYPE;
			goto cleanup;
		}

		if (buffer) {

			

			ACPI_MEMCPY(buffer, operand[0]->string.pointer + index,
				    length);
		}

		

		return_desc->string.pointer = buffer;
		return_desc->string.length = (u32) length;

		

		return_desc->buffer.flags |= AOPOBJ_DATA_VALID;
		break;

	default:

		ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
			    walk_state->opcode));
		status = AE_AML_BAD_OPCODE;
		goto cleanup;
	}

	

	status = acpi_ex_store(return_desc, operand[3], walk_state);

      cleanup:

	

	if (ACPI_FAILURE(status) || walk_state->result_obj) {
		acpi_ut_remove_reference(return_desc);
		walk_state->result_obj = NULL;
	}

	

	else {
		walk_state->result_obj = return_desc;
	}
	return_ACPI_STATUS(status);
}
Example #14
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_ex_opcode_3A_0T_0R
 *
 * PARAMETERS:  walk_state          - Current walk state
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Execute Triadic operator (3 operands)
 *
 ******************************************************************************/
acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state)
{
	union acpi_operand_object **operand = &walk_state->operands[0];
	struct acpi_signal_fatal_info *fatal;
	acpi_status status = AE_OK;

	ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_0T_0R,
				acpi_ps_get_opcode_name(walk_state->opcode));

	switch (walk_state->opcode) {
	case AML_FATAL_OP:	/* Fatal (fatal_type fatal_code fatal_arg) */

		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				  "FatalOp: Type %X Code %X Arg %X "
				  "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
				  (u32)operand[0]->integer.value,
				  (u32)operand[1]->integer.value,
				  (u32)operand[2]->integer.value));

		fatal = ACPI_ALLOCATE(sizeof(struct acpi_signal_fatal_info));
		if (fatal) {
			fatal->type = (u32) operand[0]->integer.value;
			fatal->code = (u32) operand[1]->integer.value;
			fatal->argument = (u32) operand[2]->integer.value;
		}

		/* Always signal the OS! */

		status = acpi_os_signal(ACPI_SIGNAL_FATAL, fatal);

		/* Might return while OS is shutting down, just continue */

		ACPI_FREE(fatal);
		goto cleanup;

	case AML_EXTERNAL_OP:
		/*
		 * If the interpreter sees this opcode, just ignore it. The External
		 * op is intended for use by disassemblers in order to properly
		 * disassemble control method invocations. The opcode or group of
		 * opcodes should be surrounded by an "if (0)" clause to ensure that
		 * AML interpreters never see the opcode. Thus, something is
		 * wrong if an external opcode ever gets here.
		 */
		ACPI_ERROR((AE_INFO, "Executed External Op"));
		status = AE_OK;
		goto cleanup;

	default:

		ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
			    walk_state->opcode));

		status = AE_AML_BAD_OPCODE;
		goto cleanup;
	}

cleanup:

	return_ACPI_STATUS(status);
}
Example #15
0
File: nsdump.c Project: PyroOS/Pyro
acpi_status
acpi_ns_dump_one_object(acpi_handle obj_handle,
			u32 level, void *context, void **return_value)
{
	struct acpi_walk_info *info = (struct acpi_walk_info *)context;
	struct acpi_namespace_node *this_node;
	union acpi_operand_object *obj_desc = NULL;
	acpi_object_type obj_type;
	acpi_object_type type;
	u32 bytes_to_dump;
	u32 dbg_level;
	u32 i;

	ACPI_FUNCTION_NAME(ns_dump_one_object);

	/* Is output enabled? */

	if (!(acpi_dbg_level & info->debug_level)) {
		return (AE_OK);
	}

	if (!obj_handle) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Null object handle\n"));
		return (AE_OK);
	}

	this_node = acpi_ns_map_handle_to_node(obj_handle);
	type = this_node->type;

	/* Check if the owner matches */

	if ((info->owner_id != ACPI_OWNER_ID_MAX) &&
	    (info->owner_id != this_node->owner_id)) {
		return (AE_OK);
	}

	if (!(info->display_type & ACPI_DISPLAY_SHORT)) {

		/* Indent the object according to the level */

		acpi_os_printf("%2d%*s", (u32) level - 1, (int)level * 2, " ");

		/* Check the node type and name */

		if (type > ACPI_TYPE_LOCAL_MAX) {
			ACPI_WARNING((AE_INFO, "Invalid ACPI Object Type %08X",
				      type));
		}

		if (!acpi_ut_valid_acpi_name(this_node->name.integer)) {
			this_node->name.integer =
			    acpi_ut_repair_name(this_node->name.ascii);

			ACPI_WARNING((AE_INFO, "Invalid ACPI Name %08X",
				      this_node->name.integer));
		}

		acpi_os_printf("%4.4s", acpi_ut_get_node_name(this_node));
	}

	/*
	 * Now we can print out the pertinent information
	 */
	acpi_os_printf(" %-12s %p %2.2X ",
		       acpi_ut_get_type_name(type), this_node,
		       this_node->owner_id);

	dbg_level = acpi_dbg_level;
	acpi_dbg_level = 0;
	obj_desc = acpi_ns_get_attached_object(this_node);
	acpi_dbg_level = dbg_level;

	/* Temp nodes are those nodes created by a control method */

	if (this_node->flags & ANOBJ_TEMPORARY) {
		acpi_os_printf("(T) ");
	}

	switch (info->display_type & ACPI_DISPLAY_MASK) {
	case ACPI_DISPLAY_SUMMARY:

		if (!obj_desc) {

			/* No attached object, we are done */

			acpi_os_printf("\n");
			return (AE_OK);
		}

		switch (type) {
		case ACPI_TYPE_PROCESSOR:

			acpi_os_printf("ID %X Len %.4X Addr %p\n",
				       obj_desc->processor.proc_id,
				       obj_desc->processor.length,
				       ACPI_CAST_PTR(void,
						     obj_desc->processor.
						     address));
			break;

		case ACPI_TYPE_DEVICE:

			acpi_os_printf("Notify Object: %p\n", obj_desc);
			break;

		case ACPI_TYPE_METHOD:

			acpi_os_printf("Args %X Len %.4X Aml %p\n",
				       (u32) obj_desc->method.param_count,
				       obj_desc->method.aml_length,
				       obj_desc->method.aml_start);
			break;

		case ACPI_TYPE_INTEGER:

			acpi_os_printf("= %8.8X%8.8X\n",
				       ACPI_FORMAT_UINT64(obj_desc->integer.
							  value));
			break;

		case ACPI_TYPE_PACKAGE:

			if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
				acpi_os_printf("Elements %.2X\n",
					       obj_desc->package.count);
			} else {
				acpi_os_printf("[Length not yet evaluated]\n");
			}
			break;

		case ACPI_TYPE_BUFFER:

			if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
				acpi_os_printf("Len %.2X",
					       obj_desc->buffer.length);

				/* Dump some of the buffer */

				if (obj_desc->buffer.length > 0) {
					acpi_os_printf(" =");
					for (i = 0;
					     (i < obj_desc->buffer.length
					      && i < 12); i++) {
						acpi_os_printf(" %.2hX",
							       obj_desc->buffer.
							       pointer[i]);
					}
				}
				acpi_os_printf("\n");
			} else {
				acpi_os_printf("[Length not yet evaluated]\n");
			}
			break;

		case ACPI_TYPE_STRING:

			acpi_os_printf("Len %.2X ", obj_desc->string.length);
			acpi_ut_print_string(obj_desc->string.pointer, 32);
			acpi_os_printf("\n");
			break;

		case ACPI_TYPE_REGION:

			acpi_os_printf("[%s]",
				       acpi_ut_get_region_name(obj_desc->region.
							       space_id));
			if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
				acpi_os_printf(" Addr %8.8X%8.8X Len %.4X\n",
					       ACPI_FORMAT_NATIVE_UINT
					       (obj_desc->region.address),
					       obj_desc->region.length);
			} else {
				acpi_os_printf
				    (" [Address/Length not yet evaluated]\n");
			}
			break;

		case ACPI_TYPE_LOCAL_REFERENCE:

			acpi_os_printf("[%s]\n",
				       acpi_ps_get_opcode_name(obj_desc->
							       reference.
							       opcode));
			break;

		case ACPI_TYPE_BUFFER_FIELD:

			if (obj_desc->buffer_field.buffer_obj &&
			    obj_desc->buffer_field.buffer_obj->buffer.node) {
				acpi_os_printf("Buf [%4.4s]",
					       acpi_ut_get_node_name(obj_desc->
								     buffer_field.
								     buffer_obj->
								     buffer.
								     node));
			}
			break;

		case ACPI_TYPE_LOCAL_REGION_FIELD:

			acpi_os_printf("Rgn [%4.4s]",
				       acpi_ut_get_node_name(obj_desc->
							     common_field.
							     region_obj->region.
							     node));
			break;

		case ACPI_TYPE_LOCAL_BANK_FIELD:

			acpi_os_printf("Rgn [%4.4s] Bnk [%4.4s]",
				       acpi_ut_get_node_name(obj_desc->
							     common_field.
							     region_obj->region.
							     node),
				       acpi_ut_get_node_name(obj_desc->
							     bank_field.
							     bank_obj->
							     common_field.
							     node));
			break;

		case ACPI_TYPE_LOCAL_INDEX_FIELD:

			acpi_os_printf("Idx [%4.4s] Dat [%4.4s]",
				       acpi_ut_get_node_name(obj_desc->
							     index_field.
							     index_obj->
							     common_field.node),
				       acpi_ut_get_node_name(obj_desc->
							     index_field.
							     data_obj->
							     common_field.
							     node));
			break;

		case ACPI_TYPE_LOCAL_ALIAS:
		case ACPI_TYPE_LOCAL_METHOD_ALIAS:

			acpi_os_printf("Target %4.4s (%p)\n",
				       acpi_ut_get_node_name(obj_desc),
				       obj_desc);
			break;

		default:

			acpi_os_printf("Object %p\n", obj_desc);
			break;
		}

		/* Common field handling */

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

			acpi_os_printf(" Off %.3X Len %.2X Acc %.2hd\n",
				       (obj_desc->common_field.
					base_byte_offset * 8)
				       +
				       obj_desc->common_field.
				       start_field_bit_offset,
				       obj_desc->common_field.bit_length,
				       obj_desc->common_field.
				       access_byte_width);
			break;

		default:
			break;
		}
		break;

	case ACPI_DISPLAY_OBJECTS:

		acpi_os_printf("O:%p", obj_desc);
		if (!obj_desc) {

			/* No attached object, we are done */

			acpi_os_printf("\n");
			return (AE_OK);
		}

		acpi_os_printf("(R%d)", obj_desc->common.reference_count);

		switch (type) {
		case ACPI_TYPE_METHOD:

			/* Name is a Method and its AML offset/length are set */

			acpi_os_printf(" M:%p-%X\n", obj_desc->method.aml_start,
				       obj_desc->method.aml_length);
			break;

		case ACPI_TYPE_INTEGER:

			acpi_os_printf(" I:%8.8X8.8%X\n",
				       ACPI_FORMAT_UINT64(obj_desc->integer.
							  value));
			break;

		case ACPI_TYPE_STRING:

			acpi_os_printf(" S:%p-%X\n", obj_desc->string.pointer,
				       obj_desc->string.length);
			break;

		case ACPI_TYPE_BUFFER:

			acpi_os_printf(" B:%p-%X\n", obj_desc->buffer.pointer,
				       obj_desc->buffer.length);
			break;

		default:

			acpi_os_printf("\n");
			break;
		}
		break;

	default:
		acpi_os_printf("\n");
		break;
	}

	/* If debug turned off, done */

	if (!(acpi_dbg_level & ACPI_LV_VALUES)) {
		return (AE_OK);
	}

	/* If there is an attached object, display it */

	dbg_level = acpi_dbg_level;
	acpi_dbg_level = 0;
	obj_desc = acpi_ns_get_attached_object(this_node);
	acpi_dbg_level = dbg_level;

	/* Dump attached objects */

	while (obj_desc) {
		obj_type = ACPI_TYPE_INVALID;
		acpi_os_printf("Attached Object %p: ", obj_desc);

		/* Decode the type of attached object and dump the contents */

		switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
		case ACPI_DESC_TYPE_NAMED:

			acpi_os_printf("(Ptr to Node)\n");
			bytes_to_dump = sizeof(struct acpi_namespace_node);
			ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump);
			break;

		case ACPI_DESC_TYPE_OPERAND:

			obj_type = ACPI_GET_OBJECT_TYPE(obj_desc);

			if (obj_type > ACPI_TYPE_LOCAL_MAX) {
				acpi_os_printf
				    ("(Ptr to ACPI Object type %X [UNKNOWN])\n",
				     obj_type);
				bytes_to_dump = 32;
			} else {
				acpi_os_printf
				    ("(Ptr to ACPI Object type %X [%s])\n",
				     obj_type, acpi_ut_get_type_name(obj_type));
				bytes_to_dump =
				    sizeof(union acpi_operand_object);
			}

			ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump);
			break;

		default:

			break;
		}

		/* If value is NOT an internal object, we are done */

		if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) !=
		    ACPI_DESC_TYPE_OPERAND) {
			goto cleanup;
		}

		/*
		 * Valid object, get the pointer to next level, if any
		 */
		switch (obj_type) {
		case ACPI_TYPE_BUFFER:
		case ACPI_TYPE_STRING:
			/*
			 * NOTE: takes advantage of common fields between string/buffer
			 */
			bytes_to_dump = obj_desc->string.length;
			obj_desc = (void *)obj_desc->string.pointer;
			acpi_os_printf("(Buffer/String pointer %p length %X)\n",
				       obj_desc, bytes_to_dump);
			ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump);
			goto cleanup;

		case ACPI_TYPE_BUFFER_FIELD:
			obj_desc =
			    (union acpi_operand_object *)obj_desc->buffer_field.
			    buffer_obj;
			break;

		case ACPI_TYPE_PACKAGE:
			obj_desc = (void *)obj_desc->package.elements;
			break;

		case ACPI_TYPE_METHOD:
			obj_desc = (void *)obj_desc->method.aml_start;
			break;

		case ACPI_TYPE_LOCAL_REGION_FIELD:
			obj_desc = (void *)obj_desc->field.region_obj;
			break;

		case ACPI_TYPE_LOCAL_BANK_FIELD:
			obj_desc = (void *)obj_desc->bank_field.region_obj;
			break;

		case ACPI_TYPE_LOCAL_INDEX_FIELD:
			obj_desc = (void *)obj_desc->index_field.index_obj;
			break;

		default:
			goto cleanup;
		}

		obj_type = ACPI_TYPE_INVALID;	/* Terminate loop after next pass */
	}

      cleanup:
	acpi_os_printf("\n");
	return (AE_OK);
}
acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state)
{
    union acpi_operand_object **operand = &walk_state->operands[0];
    union acpi_operand_object *return_desc = NULL;
    acpi_status status = AE_OK;
    u64 index;
    union acpi_operand_object *this_element;

    ACPI_FUNCTION_TRACE_STR(ex_opcode_6A_0T_1R,
                            acpi_ps_get_opcode_name(walk_state->opcode));

    switch (walk_state->opcode) {
    case AML_MATCH_OP:



        if ((operand[1]->integer.value > MAX_MATCH_OPERATOR) ||
                (operand[3]->integer.value > MAX_MATCH_OPERATOR)) {
            ACPI_ERROR((AE_INFO, "Match operator out of range"));
            status = AE_AML_OPERAND_VALUE;
            goto cleanup;
        }



        index = operand[5]->integer.value;
        if (index >= operand[0]->package.count) {
            ACPI_ERROR((AE_INFO,
                        "Index (0x%8.8X%8.8X) beyond package end (0x%X)",
                        ACPI_FORMAT_UINT64(index),
                        operand[0]->package.count));
            status = AE_AML_PACKAGE_LIMIT;
            goto cleanup;
        }




        return_desc = acpi_ut_create_integer_object(ACPI_UINT64_MAX);
        if (!return_desc) {
            status = AE_NO_MEMORY;
            goto cleanup;

        }

        for (; index < operand[0]->package.count; index++) {



            this_element = operand[0]->package.elements[index];



            if (!this_element) {
                continue;
            }

            if (!acpi_ex_do_match((u32) operand[1]->integer.value,
                                  this_element, operand[2])) {
                continue;
            }

            if (!acpi_ex_do_match((u32) operand[3]->integer.value,
                                  this_element, operand[4])) {
                continue;
            }



            return_desc->integer.value = index;
            break;
        }
        break;

    case AML_LOAD_TABLE_OP:

        status = acpi_ex_load_table_op(walk_state, &return_desc);
        break;

    default:

        ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
                    walk_state->opcode));
        status = AE_AML_BAD_OPCODE;
        goto cleanup;
    }

cleanup:



    if (ACPI_FAILURE(status)) {
        acpi_ut_remove_reference(return_desc);
    }



    else {
        walk_state->result_obj = return_desc;
    }

    return_ACPI_STATUS(status);
}
Example #17
0
acpi_status
acpi_ex_opcode_2A_0T_1R (
	acpi_walk_state         *walk_state)
{
	acpi_operand_object     **operand = &walk_state->operands[0];
	acpi_operand_object     *return_desc = NULL;
	acpi_status             status = AE_OK;
	u8                      logical_result = FALSE;


	FUNCTION_TRACE_STR ("Ex_opcode_2A_0T_1R", acpi_ps_get_opcode_name (walk_state->opcode));


	/* Create the internal return object */

	return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
	if (!return_desc) {
		status = AE_NO_MEMORY;
		goto cleanup;
	}

	/*
	 * Execute the Opcode
	 */
	if (walk_state->op_info->flags & AML_LOGICAL) /* Logical_op (Operand0, Operand1) */ {
		logical_result = acpi_ex_do_logical_op (walk_state->opcode,
				 operand[0]->integer.value,
				 operand[1]->integer.value);
		goto store_logical_result;
	}


	switch (walk_state->opcode) {
	case AML_ACQUIRE_OP:            /* Acquire (Mutex_object, Timeout) */

		status = acpi_ex_acquire_mutex (operand[1], operand[0], walk_state);
		if (status == AE_TIME) {
			logical_result = TRUE;      /* TRUE = Acquire timed out */
			status = AE_OK;
		}
		break;


	case AML_WAIT_OP:               /* Wait (Event_object, Timeout) */

		status = acpi_ex_system_wait_event (operand[1], operand[0]);
		if (status == AE_TIME) {
			logical_result = TRUE;      /* TRUE, Wait timed out */
			status = AE_OK;
		}
		break;


	default:

		REPORT_ERROR (("Acpi_ex_opcode_2A_0T_1R: Unknown opcode %X\n", walk_state->opcode));
		status = AE_AML_BAD_OPCODE;
		goto cleanup;
		break;
	}


store_logical_result:
	/*
	 * Set return value to according to Logical_result. logical TRUE (all ones)
	 * Default is FALSE (zero)
	 */
	if (logical_result) {
		return_desc->integer.value = ACPI_INTEGER_MAX;
	}

	walk_state->result_obj = return_desc;


cleanup:

	/* Delete return object on error */

	if (ACPI_FAILURE (status)) {
		acpi_ut_remove_reference (return_desc);
	}

	return_ACPI_STATUS (status);
}
Example #18
0
acpi_status
acpi_ds_load2_end_op (
	acpi_walk_state         *walk_state)
{
	acpi_parse_object       *op;
	acpi_status             status = AE_OK;
	acpi_object_type8       data_type;
	acpi_namespace_node     *node;
	acpi_parse_object       *arg;
	acpi_namespace_node     *new_node;
	u32                     i;


	PROC_NAME ("Ds_load2_end_op");

	op = walk_state->op;
	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state));


	/* Only interested in opcodes that have namespace objects */

	if (!(walk_state->op_info->flags & AML_NSOBJECT)) {
		return (AE_OK);
	}

	if (op->opcode == AML_SCOPE_OP) {
		ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
			"Ending scope Op=%p State=%p\n", op, walk_state));

		if (((acpi_parse2_object *)op)->name == -1) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unnamed scope! Op=%p State=%p\n",
				op, walk_state));
			return (AE_OK);
		}
	}


	data_type = acpi_ds_map_named_opcode_to_data_type (op->opcode);

	/*
	 * Get the Node/name from the earlier lookup
	 * (It was saved in the *op structure)
	 */
	node = op->node;

	/*
	 * Put the Node on the object stack (Contains the ACPI Name of
	 * this object)
	 */
	walk_state->operands[0] = (void *) node;
	walk_state->num_operands = 1;

	/* Pop the scope stack */

	if (acpi_ns_opens_scope (data_type)) {

		ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s) Popping scope for Op %p\n",
			acpi_ut_get_type_name (data_type), op));
		acpi_ds_scope_stack_pop (walk_state);
	}

	/*
	 * Named operations are as follows:
	 *
	 * AML_ALIAS
	 * AML_BANKFIELD
	 * AML_CREATEBITFIELD
	 * AML_CREATEBYTEFIELD
	 * AML_CREATEDWORDFIELD
	 * AML_CREATEFIELD
	 * AML_CREATEQWORDFIELD
	 * AML_CREATEWORDFIELD
	 * AML_DATA_REGION
	 * AML_DEVICE
	 * AML_EVENT
	 * AML_FIELD
	 * AML_INDEXFIELD
	 * AML_METHOD
	 * AML_METHODCALL
	 * AML_MUTEX
	 * AML_NAME
	 * AML_NAMEDFIELD
	 * AML_OPREGION
	 * AML_POWERRES
	 * AML_PROCESSOR
	 * AML_SCOPE
	 * AML_THERMALZONE
	 */

	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
		"Create-Load [%s] State=%p Op=%p Named_obj=%p\n",
		acpi_ps_get_opcode_name (op->opcode), walk_state, op, node));

	/* Decode the opcode */

	arg = op->value.arg;

	switch (walk_state->op_info->type) {
	case AML_TYPE_CREATE_FIELD:

		/*
		 * Create the field object, but the field buffer and index must
		 * be evaluated later during the execution phase
		 */
		status = acpi_ds_create_buffer_field (op, walk_state);
		break;


	 case AML_TYPE_NAMED_FIELD:

		arg = op->value.arg;
		switch (op->opcode) {
		case AML_INDEX_FIELD_OP:

			status = acpi_ds_create_index_field (op, (acpi_handle) arg->node,
					   walk_state);
			break;


		case AML_BANK_FIELD_OP:

			status = acpi_ds_create_bank_field (op, arg->node, walk_state);
			break;


		case AML_FIELD_OP:

			status = acpi_ds_create_field (op, arg->node, walk_state);
			break;
		}
		break;


	 case AML_TYPE_NAMED_SIMPLE:

		status = acpi_ds_create_operands (walk_state, arg);
		if (ACPI_FAILURE (status)) {
			goto cleanup;
		}

		switch (op->opcode) {
		case AML_PROCESSOR_OP:

			status = acpi_ex_create_processor (walk_state);
			break;


		case AML_POWER_RES_OP:

			status = acpi_ex_create_power_resource (walk_state);
			break;


		case AML_MUTEX_OP:

			status = acpi_ex_create_mutex (walk_state);
			break;


		case AML_EVENT_OP:

			status = acpi_ex_create_event (walk_state);
			break;


		case AML_DATA_REGION_OP:

			status = acpi_ex_create_table_region (walk_state);
			break;

		case AML_ALIAS_OP:

			status = acpi_ex_create_alias (walk_state);
			break;

		default:
			/* Unknown opcode */

			status = AE_OK;
			goto cleanup;
			break;
		}

		/* Delete operands */

		for (i = 1; i < walk_state->num_operands; i++) {
			acpi_ut_remove_reference (walk_state->operands[i]);
			walk_state->operands[i] = NULL;
		}

		break;


	case AML_TYPE_NAMED_COMPLEX:

		switch (op->opcode) {
		case AML_METHOD_OP:
			/*
			 * Method_op Pkg_length Names_string Method_flags Term_list
			 */
			ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
				"LOADING-Method: State=%p Op=%p Named_obj=%p\n",
				walk_state, op, node));

			if (!node->object) {
				status = acpi_ds_create_operands (walk_state, arg);
				if (ACPI_FAILURE (status)) {
					goto cleanup;
				}

				status = acpi_ex_create_method (((acpi_parse2_object *) op)->data,
						   ((acpi_parse2_object *) op)->length,
						   walk_state);
			}
			break;


		case AML_REGION_OP:
			/*
			 * The Op_region is not fully parsed at this time. Only valid argument is the Space_id.
			 * (We must save the address of the AML of the address and length operands)
			 */
			status = acpi_ex_create_region (((acpi_parse2_object *) op)->data,
					  ((acpi_parse2_object *) op)->length,
							 (ACPI_ADR_SPACE_TYPE) arg->value.integer, walk_state);
			break;


		case AML_NAME_OP:

			status = acpi_ds_create_node (walk_state, node, op);
			break;
		}
		break;


	case AML_CLASS_INTERNAL:

		/* case AML_INT_NAMEPATH_OP: */
		break;


	case AML_CLASS_METHOD_CALL:

		ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
			"RESOLVING-Method_call: State=%p Op=%p Named_obj=%p\n",
			walk_state, op, node));

		/*
		 * Lookup the method name and save the Node
		 */
		status = acpi_ns_lookup (walk_state->scope_info, arg->value.string,
				  ACPI_TYPE_ANY, IMODE_LOAD_PASS2,
				  NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE,
				  walk_state, &(new_node));
		if (ACPI_SUCCESS (status)) {
			/* TBD: has name already been resolved by here ??*/

			/* TBD: [Restructure] Make sure that what we found is indeed a method! */
			/* We didn't search for a method on purpose, to see if the name would resolve! */

			/* We could put the returned object (Node) on the object stack for later, but
			 * for now, we will put it in the "op" object that the parser uses, so we
			 * can get it again at the end of this scope
			 */
			op->node = new_node;
		}

		break;


	default:
		break;
	}


cleanup:

	/* Remove the Node pushed at the very beginning */

	walk_state->operands[0] = NULL;
	walk_state->num_operands = 0;
	return (status);
}
Example #19
0
acpi_status
acpi_ex_resolve_node_to_value (
	struct acpi_namespace_node      **object_ptr,
	struct acpi_walk_state          *walk_state)

{
	acpi_status                     status = AE_OK;
	union acpi_operand_object       *source_desc;
	union acpi_operand_object       *obj_desc = NULL;
	struct acpi_namespace_node      *node;
	acpi_object_type                entry_type;


	ACPI_FUNCTION_TRACE ("ex_resolve_node_to_value");


	/*
	 * The stack pointer points to a struct acpi_namespace_node (Node).  Get the
	 * object that is attached to the Node.
	 */
	node       = *object_ptr;
	source_desc = acpi_ns_get_attached_object (node);
	entry_type = acpi_ns_get_type ((acpi_handle) node);

	ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Entry=%p source_desc=%p [%s]\n",
		 node, source_desc, acpi_ut_get_type_name (entry_type)));

	if (entry_type == ACPI_TYPE_LOCAL_ALIAS) {
		/* There is always exactly one level of indirection */

		node       = (struct acpi_namespace_node *) node->object;
		source_desc = acpi_ns_get_attached_object (node);
		entry_type = acpi_ns_get_type ((acpi_handle) node);
		*object_ptr = node;
	}

	/*
	 * Several object types require no further processing:
	 * 1) Devices rarely have an attached object, return the Node
	 * 2) Method locals and arguments have a pseudo-Node
	 */
	if (entry_type == ACPI_TYPE_DEVICE ||
		(node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) {
		return_ACPI_STATUS (AE_OK);
	}

	if (!source_desc) {
		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No object attached to node %p\n",
			node));
		return_ACPI_STATUS (AE_AML_NO_OPERAND);
	}

	/*
	 * Action is based on the type of the Node, which indicates the type
	 * of the attached object or pointer
	 */
	switch (entry_type) {
	case ACPI_TYPE_PACKAGE:

		if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_PACKAGE) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a Package, type %s\n",
				acpi_ut_get_object_type_name (source_desc)));
			return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
		}

		status = acpi_ds_get_package_arguments (source_desc);
		if (ACPI_SUCCESS (status)) {
			/* Return an additional reference to the object */

			obj_desc = source_desc;
			acpi_ut_add_reference (obj_desc);
		}
		break;


	case ACPI_TYPE_BUFFER:

		if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_BUFFER) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a Buffer, type %s\n",
				acpi_ut_get_object_type_name (source_desc)));
			return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
		}

		status = acpi_ds_get_buffer_arguments (source_desc);
		if (ACPI_SUCCESS (status)) {
			/* Return an additional reference to the object */

			obj_desc = source_desc;
			acpi_ut_add_reference (obj_desc);
		}
		break;


	case ACPI_TYPE_STRING:

		if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_STRING) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a String, type %s\n",
				acpi_ut_get_object_type_name (source_desc)));
			return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
		}

		/* Return an additional reference to the object */

		obj_desc = source_desc;
		acpi_ut_add_reference (obj_desc);
		break;


	case ACPI_TYPE_INTEGER:

		if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_INTEGER) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a Integer, type %s\n",
				acpi_ut_get_object_type_name (source_desc)));
			return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
		}

		/* Return an additional reference to the object */

		obj_desc = source_desc;
		acpi_ut_add_reference (obj_desc);
		break;


	case ACPI_TYPE_BUFFER_FIELD:
	case ACPI_TYPE_LOCAL_REGION_FIELD:
	case ACPI_TYPE_LOCAL_BANK_FIELD:
	case ACPI_TYPE_LOCAL_INDEX_FIELD:

		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "field_read Node=%p source_desc=%p Type=%X\n",
			node, source_desc, entry_type));

		status = acpi_ex_read_data_from_field (walk_state, source_desc, &obj_desc);
		break;

	/*
	 * For these objects, just return the object attached to the Node
	 */
	case ACPI_TYPE_MUTEX:
	case ACPI_TYPE_METHOD:
	case ACPI_TYPE_POWER:
	case ACPI_TYPE_PROCESSOR:
	case ACPI_TYPE_THERMAL:
	case ACPI_TYPE_EVENT:
	case ACPI_TYPE_REGION:

		/* Return an additional reference to the object */

		obj_desc = source_desc;
		acpi_ut_add_reference (obj_desc);
		break;


	/* TYPE_ANY is untyped, and thus there is no object associated with it */

	case ACPI_TYPE_ANY:

		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Untyped entry %p, no attached object!\n",
			node));

		return_ACPI_STATUS (AE_AML_OPERAND_TYPE);  /* Cannot be AE_TYPE */


	case ACPI_TYPE_LOCAL_REFERENCE:

		switch (source_desc->reference.opcode) {
		case AML_LOAD_OP:

			/* This is a ddb_handle */
			/* Return an additional reference to the object */

			obj_desc = source_desc;
			acpi_ut_add_reference (obj_desc);
			break;

		default:
			/* No named references are allowed here */

			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unsupported Reference opcode %X (%s)\n",
				source_desc->reference.opcode,
				acpi_ps_get_opcode_name (source_desc->reference.opcode)));

			return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
		}
		break;


	/* Default case is for unknown types */

	default:

		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Node %p - Unknown object type %X\n",
			node, entry_type));

		return_ACPI_STATUS (AE_AML_OPERAND_TYPE);

	} /* switch (entry_type) */


	/* Put the object descriptor on the stack */

	*object_ptr = (void *) obj_desc;
	return_ACPI_STATUS (status);
}
Example #20
0
static void
acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
			u32 level, u32 index)
{
	u32 i;

	ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc);

	/* Print line header as long as we are not in the middle of an object display */

	if (!((level > 0) && index == 0)) {
		ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %*s",
				      level, " "));
	}

	/* Display index for package output only */

	if (index > 0) {
		ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
				      "(%.2u) ", index - 1));
	}

	if (!source_desc) {
		ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[Null Object]\n"));
		return_VOID;
	}

	if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) {
		ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s ",
				      acpi_ut_get_object_type_name
				      (source_desc)));

		if (!acpi_ut_valid_internal_object(source_desc)) {
			ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
					      "%p, Invalid Internal Object!\n",
					      source_desc));
			return_VOID;
		}
	} else if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) ==
		   ACPI_DESC_TYPE_NAMED) {
		ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s: %p\n",
				      acpi_ut_get_type_name(((struct
							      acpi_namespace_node
							      *)source_desc)->
							    type),
				      source_desc));
		return_VOID;
	} else {
		return_VOID;
	}

	/* source_desc is of type ACPI_DESC_TYPE_OPERAND */

	switch (ACPI_GET_OBJECT_TYPE(source_desc)) {
	case ACPI_TYPE_INTEGER:

		/* Output correct integer width */

		if (acpi_gbl_integer_byte_width == 4) {
			ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "0x%8.8X\n",
					      (u32) source_desc->integer.
					      value));
		} else {
			ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
					      "0x%8.8X%8.8X\n",
					      ACPI_FORMAT_UINT64(source_desc->
								 integer.
								 value)));
		}
		break;

	case ACPI_TYPE_BUFFER:

		ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[0x%.2X]\n",
				      (u32) source_desc->buffer.length));
		ACPI_DUMP_BUFFER(source_desc->buffer.pointer,
				 (source_desc->buffer.length <
				  256) ? source_desc->buffer.length : 256);
		break;

	case ACPI_TYPE_STRING:

		ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[0x%.2X] \"%s\"\n",
				      source_desc->string.length,
				      source_desc->string.pointer));
		break;

	case ACPI_TYPE_PACKAGE:

		ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
				      "[Contains 0x%.2X Elements]\n",
				      source_desc->package.count));

		/* Output the entire contents of the package */

		for (i = 0; i < source_desc->package.count; i++) {
			acpi_ex_do_debug_object(source_desc->package.
						elements[i], level + 4, i + 1);
		}
		break;

	case ACPI_TYPE_LOCAL_REFERENCE:

		if (source_desc->reference.opcode == AML_INDEX_OP) {
			ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
					      "[%s, 0x%X]\n",
					      acpi_ps_get_opcode_name
					      (source_desc->reference.opcode),
					      source_desc->reference.offset));
		} else {
			ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s]",
					      acpi_ps_get_opcode_name
					      (source_desc->reference.opcode)));
		}

		if (source_desc->reference.opcode == AML_LOAD_OP) {	/* Load and load_table */
			ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
					      " Table OwnerId %p\n",
					      source_desc->reference.object));
			break;
		}

		ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "  "));

		/* Check for valid node first, then valid object */

		if (source_desc->reference.node) {
			if (ACPI_GET_DESCRIPTOR_TYPE
			    (source_desc->reference.node) !=
			    ACPI_DESC_TYPE_NAMED) {
				ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
						      " %p - Not a valid namespace node\n",
						      source_desc->reference.
						      node));
			} else {
				ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
						      "Node %p [%4.4s] ",
						      source_desc->reference.
						      node,
						      (source_desc->reference.
						       node)->name.ascii));

				switch ((source_desc->reference.node)->type) {

					/* These types have no attached object */

				case ACPI_TYPE_DEVICE:
					acpi_os_printf("Device\n");
					break;

				case ACPI_TYPE_THERMAL:
					acpi_os_printf("Thermal Zone\n");
					break;

				default:
					acpi_ex_do_debug_object((source_desc->
								 reference.
								 node)->object,
								level + 4, 0);
					break;
				}
			}
		} else if (source_desc->reference.object) {
			if (ACPI_GET_DESCRIPTOR_TYPE
			    (source_desc->reference.object) ==
			    ACPI_DESC_TYPE_NAMED) {
				acpi_ex_do_debug_object(((struct
							  acpi_namespace_node *)
							 source_desc->reference.
							 object)->object,
							level + 4, 0);
			} else {
				acpi_ex_do_debug_object(source_desc->reference.
							object, level + 4, 0);
			}
		}
		break;

	default:

		ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%p\n",
				      source_desc));
		break;
	}

	ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "\n"));
	return_VOID;
}
Example #21
0
acpi_status
acpi_ex_opcode_2A_1T_1R (
	acpi_walk_state         *walk_state)
{
	acpi_operand_object     **operand   = &walk_state->operands[0];
	acpi_operand_object     *return_desc = NULL;
	acpi_operand_object     *temp_desc;
	u32                     index;
	acpi_status             status      = AE_OK;


	FUNCTION_TRACE_STR ("Ex_opcode_2A_1T_1R", acpi_ps_get_opcode_name (walk_state->opcode));


	/*
	 * Execute the opcode
	 */
	if (walk_state->op_info->flags & AML_MATH) {
		/* All simple math opcodes (add, etc.) */

		return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
		if (!return_desc) {
			status = AE_NO_MEMORY;
			goto cleanup;
		}

		return_desc->integer.value = acpi_ex_do_math_op (walk_state->opcode,
				  operand[0]->integer.value,
				  operand[1]->integer.value);
		goto store_result_to_target;
	}


	switch (walk_state->opcode) {
	case AML_MOD_OP:                /* Mod (Dividend, Divisor, Remainder_result (ACPI 2.0) */

		return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
		if (!return_desc) {
			status = AE_NO_MEMORY;
			goto cleanup;
		}

		/* Return_desc will contain the remainder */

		status = acpi_ut_divide (&operand[0]->integer.value, &operand[1]->integer.value,
				  NULL, &return_desc->integer.value);

		break;


	case AML_CONCAT_OP:             /* Concatenate (Data1, Data2, Result) */

		/*
		 * Convert the second operand if necessary.  The first operand
		 * determines the type of the second operand, (See the Data Types
		 * section of the ACPI specification.)  Both object types are
		 * guaranteed to be either Integer/String/Buffer by the operand
		 * resolution mechanism above.
		 */
		switch (operand[0]->common.type) {
		case ACPI_TYPE_INTEGER:
			status = acpi_ex_convert_to_integer (operand[1], &operand[1], walk_state);
			break;

		case ACPI_TYPE_STRING:
			status = acpi_ex_convert_to_string (operand[1], &operand[1], 16, ACPI_UINT32_MAX, walk_state);
			break;

		case ACPI_TYPE_BUFFER:
			status = acpi_ex_convert_to_buffer (operand[1], &operand[1], walk_state);
			break;

		default:
			status = AE_AML_INTERNAL;
		}

		if (ACPI_FAILURE (status)) {
			goto cleanup;
		}

		/*
		 * Both operands are now known to be the same object type
		 * (Both are Integer, String, or Buffer), and we can now perform the
		 * concatenation.
		 */
		status = acpi_ex_do_concatenate (operand[0], operand[1], &return_desc, walk_state);
		break;


	case AML_TO_STRING_OP:          /* To_string (Buffer, Length, Result) (ACPI 2.0) */

		status = acpi_ex_convert_to_string (operand[0], &return_desc, 16,
				  (u32) operand[1]->integer.value, walk_state);
		break;


	case AML_CONCAT_RES_OP:         /* Concatenate_res_template (Buffer, Buffer, Result) (ACPI 2.0) */

		status = AE_NOT_IMPLEMENTED;
		break;


	case AML_INDEX_OP:              /* Index (Source Index Result) */

		/* Create the internal return object */

		return_desc = acpi_ut_create_internal_object (INTERNAL_TYPE_REFERENCE);
		if (!return_desc) {
			status = AE_NO_MEMORY;
			goto cleanup;
		}

		index = (u32) operand[1]->integer.value;

		/*
		 * At this point, the Source operand is either a Package or a Buffer
		 */
		if (operand[0]->common.type == ACPI_TYPE_PACKAGE) {
			/* Object to be indexed is a Package */

			if (index >= operand[0]->package.count) {
				ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Index value beyond package end\n"));
				status = AE_AML_PACKAGE_LIMIT;
				goto cleanup;
			}

			if ((operand[2]->common.type == INTERNAL_TYPE_REFERENCE) &&
				(operand[2]->reference.opcode == AML_ZERO_OP)) {
				/*
				 * There is no actual result descriptor (the Zero_op Result
				 * descriptor is a placeholder), so just delete the placeholder and
				 * return a reference to the package element
				 */
				acpi_ut_remove_reference (operand[2]);
			}

			else {
				/*
				 * Each element of the package is an internal object.  Get the one
				 * we are after.
				 */
				temp_desc                        = operand[0]->package.elements [index];
				return_desc->reference.opcode    = AML_INDEX_OP;
				return_desc->reference.target_type = temp_desc->common.type;
				return_desc->reference.object    = temp_desc;

				status = acpi_ex_store (return_desc, operand[2], walk_state);
				return_desc->reference.object    = NULL;
			}

			/*
			 * The local return object must always be a reference to the package element,
			 * not the element itself.
			 */
			return_desc->reference.opcode    = AML_INDEX_OP;
			return_desc->reference.target_type = ACPI_TYPE_PACKAGE;
			return_desc->reference.where     = &operand[0]->package.elements [index];
		}

		else {
			/* Object to be indexed is a Buffer */

			if (index >= operand[0]->buffer.length) {
				ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Index value beyond end of buffer\n"));
				status = AE_AML_BUFFER_LIMIT;
				goto cleanup;
			}

			return_desc->reference.opcode      = AML_INDEX_OP;
			return_desc->reference.target_type = ACPI_TYPE_BUFFER_FIELD;
			return_desc->reference.object      = operand[0];
			return_desc->reference.offset      = index;

			status = acpi_ex_store (return_desc, operand[2], walk_state);
		}

		walk_state->result_obj = return_desc;
		goto cleanup;
		break;


	default:

		REPORT_ERROR (("Acpi_ex_opcode_2A_1T_1R: Unknown opcode %X\n",
				walk_state->opcode));
		status = AE_AML_BAD_OPCODE;
		break;
	}


store_result_to_target:

	if (ACPI_SUCCESS (status)) {
		/*
		 * Store the result of the operation (which is now in Return_desc) into
		 * the Target descriptor.
		 */
		status = acpi_ex_store (return_desc, operand[2], walk_state);
		if (ACPI_FAILURE (status)) {
			goto cleanup;
		}

		walk_state->result_obj = return_desc;
	}


cleanup:

	/* Delete return object on error */

	if (ACPI_FAILURE (status)) {
		acpi_ut_remove_reference (return_desc);
	}

	return_ACPI_STATUS (status);
}
Example #22
0
static void
acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
			u32 level, u32 index)
{
	u32 i;

	ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc);

	ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %*s",
			      level, " "));

	/* Display index for package output only */

	if (index > 0) {
		ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
				      "(%.2u) ", index - 1));
	}

	if (!source_desc) {
		ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "<Null Object>\n"));
		return_VOID;
	}

	if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) {
		ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s: ",
				      acpi_ut_get_object_type_name
				      (source_desc)));

		if (!acpi_ut_valid_internal_object(source_desc)) {
			ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
					      "%p, Invalid Internal Object!\n",
					      source_desc));
			return_VOID;
		}
	} else if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) ==
		   ACPI_DESC_TYPE_NAMED) {
		ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s: %p\n",
				      acpi_ut_get_type_name(((struct
							      acpi_namespace_node
							      *)source_desc)->
							    type),
				      source_desc));
		return_VOID;
	} else {
		return_VOID;
	}

	switch (ACPI_GET_OBJECT_TYPE(source_desc)) {
	case ACPI_TYPE_INTEGER:

		/* Output correct integer width */

		if (acpi_gbl_integer_byte_width == 4) {
			ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "0x%8.8X\n",
					      (u32) source_desc->integer.
					      value));
		} else {
			ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
					      "0x%8.8X%8.8X\n",
					      ACPI_FORMAT_UINT64(source_desc->
								 integer.
								 value)));
		}
		break;

	case ACPI_TYPE_BUFFER:

		ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[0x%.2X]\n",
				      (u32) source_desc->buffer.length));
		ACPI_DUMP_BUFFER(source_desc->buffer.pointer,
				 (source_desc->buffer.length <
				  32) ? source_desc->buffer.length : 32);
		break;

	case ACPI_TYPE_STRING:

		ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[0x%.2X] \"%s\"\n",
				      source_desc->string.length,
				      source_desc->string.pointer));
		break;

	case ACPI_TYPE_PACKAGE:

		ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
				      "[0x%.2X Elements]\n",
				      source_desc->package.count));

		/* Output the entire contents of the package */

		for (i = 0; i < source_desc->package.count; i++) {
			acpi_ex_do_debug_object(source_desc->package.
						elements[i], level + 4, i + 1);
		}
		break;

	case ACPI_TYPE_LOCAL_REFERENCE:

		if (source_desc->reference.opcode == AML_INDEX_OP) {
			ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT,
					      "[%s, 0x%X]\n",
					      acpi_ps_get_opcode_name
					      (source_desc->reference.opcode),
					      source_desc->reference.offset));
		} else {
			ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s]\n",
					      acpi_ps_get_opcode_name
					      (source_desc->reference.opcode)));
		}

		if (source_desc->reference.object) {
			if (ACPI_GET_DESCRIPTOR_TYPE
			    (source_desc->reference.object) ==
			    ACPI_DESC_TYPE_NAMED) {
				acpi_ex_do_debug_object(((struct
							  acpi_namespace_node *)
							 source_desc->reference.
							 object)->object,
							level + 4, 0);
			} else {
				acpi_ex_do_debug_object(source_desc->reference.
							object, level + 4, 0);
			}
		} else if (source_desc->reference.node) {
			acpi_ex_do_debug_object((source_desc->reference.node)->
						object, level + 4, 0);
		}
		break;

	default:

		ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%p %s\n",
				      source_desc,
				      acpi_ut_get_object_type_name
				      (source_desc)));
		break;
	}

	ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "\n"));
	return_VOID;
}
Example #23
0
acpi_status
acpi_ex_opcode_6A_0T_1R (
	acpi_walk_state         *walk_state)
{
	acpi_operand_object     **operand = &walk_state->operands[0];
	acpi_operand_object     *return_desc = NULL;
	acpi_status             status = AE_OK;
	u32                     index;
	acpi_operand_object     *this_element;


	FUNCTION_TRACE_STR ("Ex_opcode_6A_0T_1R", acpi_ps_get_opcode_name (walk_state->opcode));


	switch (walk_state->opcode) {
	case AML_MATCH_OP:
		/*
		 * Match (Search_package[0], Match_op1[1], Match_object1[2],
		 *                          Match_op2[3], Match_object2[4], Start_index[5])
		 */

		/* Validate match comparison sub-opcodes */

		if ((operand[1]->integer.value > MAX_MATCH_OPERATOR) ||
			(operand[3]->integer.value > MAX_MATCH_OPERATOR)) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "operation encoding out of range\n"));
			status = AE_AML_OPERAND_VALUE;
			goto cleanup;
		}

		index = (u32) operand[5]->integer.value;
		if (index >= (u32) operand[0]->package.count) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Index beyond package end\n"));
			status = AE_AML_PACKAGE_LIMIT;
			goto cleanup;
		}

		return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
		if (!return_desc) {
			status = AE_NO_MEMORY;
			goto cleanup;

		}

		/* Default return value if no match found */

		return_desc->integer.value = ACPI_INTEGER_MAX;

		/*
		 * Examine each element until a match is found.  Within the loop,
		 * "continue" signifies that the current element does not match
		 * and the next should be examined.
		 * Upon finding a match, the loop will terminate via "break" at
		 * the bottom.  If it terminates "normally", Match_value will be -1
		 * (its initial value) indicating that no match was found.  When
		 * returned as a Number, this will produce the Ones value as specified.
		 */
		for ( ; index < operand[0]->package.count; index++) {
			this_element = operand[0]->package.elements[index];

			/*
			 * Treat any NULL or non-numeric elements as non-matching.
			 * TBD [Unhandled] - if an element is a Name,
			 *      should we examine its value?
			 */
			if (!this_element ||
				this_element->common.type != ACPI_TYPE_INTEGER) {
				continue;
			}


			/*
			 * Within these switch statements:
			 *      "break" (exit from the switch) signifies a match;
			 *      "continue" (proceed to next iteration of enclosing
			 *          "for" loop) signifies a non-match.
			 */
			if (!acpi_ex_do_match ((u32) operand[1]->integer.value,
					   this_element->integer.value, operand[2]->integer.value)) {
				continue;
			}


			if (!acpi_ex_do_match ((u32) operand[3]->integer.value,
					   this_element->integer.value, operand[4]->integer.value)) {
				continue;
			}

			/* Match found: Index is the return value */

			return_desc->integer.value = index;
			break;
		}

		break;


	case AML_LOAD_TABLE_OP:

		status = AE_NOT_IMPLEMENTED;
		goto cleanup;
		break;


	default:

		REPORT_ERROR (("Acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n",
				walk_state->opcode));
		status = AE_AML_BAD_OPCODE;
		goto cleanup;
		break;
	}


	walk_state->result_obj = return_desc;


cleanup:

	/* Delete return object on error */

	if (ACPI_FAILURE (status)) {
		acpi_ut_remove_reference (return_desc);
	}

	return_ACPI_STATUS (status);
}
/*******************************************************************************
 *
 * FUNCTION:    acpi_ex_opcode_2A_0T_0R
 *
 * PARAMETERS:  walk_state          - Current walk state
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Execute opcode with two arguments, no target, and no return
 *              value.
 *
 * ALLOCATION:  Deletes both operands
 *
 ******************************************************************************/
acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state)
{
	union acpi_operand_object **operand = &walk_state->operands[0];
	struct acpi_namespace_node *node;
	u32 value;
	acpi_status status = AE_OK;

	ACPI_FUNCTION_TRACE_STR("ex_opcode_2A_0T_0R",
				acpi_ps_get_opcode_name(walk_state->opcode));

	/* Examine the opcode */

	switch (walk_state->opcode) {
	case AML_NOTIFY_OP:	/* Notify (notify_object, notify_value) */

		/* The first operand is a namespace node */

		node = (struct acpi_namespace_node *)operand[0];

		/* Second value is the notify value */

		value = (u32) operand[1]->integer.value;

		/* Are notifies allowed on this object? */

		if (!acpi_ev_is_notify_object(node)) {
			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
					  "Unexpected notify object type [%s]\n",
					  acpi_ut_get_type_name(node->type)));

			status = AE_AML_OPERAND_TYPE;
			break;
		}
#ifdef ACPI_GPE_NOTIFY_CHECK
		/*
		 * GPE method wake/notify check.  Here, we want to ensure that we
		 * don't receive any "device_wake" Notifies from a GPE _Lxx or _Exx
		 * GPE method during system runtime.  If we do, the GPE is marked
		 * as "wake-only" and disabled.
		 *
		 * 1) Is the Notify() value == device_wake?
		 * 2) Is this a GPE deferred method?  (An _Lxx or _Exx method)
		 * 3) Did the original GPE happen at system runtime?
		 *    (versus during wake)
		 *
		 * If all three cases are true, this is a wake-only GPE that should
		 * be disabled at runtime.
		 */
		if (value == 2) {	/* device_wake */
			status =
			    acpi_ev_check_for_wake_only_gpe(walk_state->
							    gpe_event_info);
			if (ACPI_FAILURE(status)) {
				/* AE_WAKE_ONLY_GPE only error, means ignore this notify */

				return_ACPI_STATUS(AE_OK)
			}
		}
#endif

		/*
		 * Dispatch the notify to the appropriate handler
		 * NOTE: the request is queued for execution after this method
		 * completes.  The notify handlers are NOT invoked synchronously
		 * from this thread -- because handlers may in turn run other
		 * control methods.
		 */
		status = acpi_ev_queue_notify_request(node, value);
		break;

	default:

		ACPI_REPORT_ERROR(("acpi_ex_opcode_2A_0T_0R: Unknown opcode %X\n", walk_state->opcode));
		status = AE_AML_BAD_OPCODE;
	}
Example #25
0
acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)
{
	acpi_status status = AE_OK;
	union acpi_operand_object **operand = &walk_state->operands[0];
	union acpi_operand_object *return_desc = NULL;
	union acpi_operand_object *return_desc2 = NULL;
	u32 temp32;
	u32 i;
	acpi_integer power_of_ten;
	acpi_integer digit;

	ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_1T_1R,
				acpi_ps_get_opcode_name(walk_state->opcode));

	/* Examine the AML opcode */

	switch (walk_state->opcode) {
	case AML_BIT_NOT_OP:
	case AML_FIND_SET_LEFT_BIT_OP:
	case AML_FIND_SET_RIGHT_BIT_OP:
	case AML_FROM_BCD_OP:
	case AML_TO_BCD_OP:
	case AML_COND_REF_OF_OP:

		/* Create a return object of type Integer for these opcodes */

		return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
		if (!return_desc) {
			status = AE_NO_MEMORY;
			goto cleanup;
		}

		switch (walk_state->opcode) {
		case AML_BIT_NOT_OP:	/* Not (Operand, Result)  */

			return_desc->integer.value = ~operand[0]->integer.value;
			break;

		case AML_FIND_SET_LEFT_BIT_OP:	/* find_set_left_bit (Operand, Result) */

			return_desc->integer.value = operand[0]->integer.value;

			/*
			 * Acpi specification describes Integer type as a little
			 * endian unsigned value, so this boundary condition is valid.
			 */
			for (temp32 = 0; return_desc->integer.value &&
			     temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) {
				return_desc->integer.value >>= 1;
			}

			return_desc->integer.value = temp32;
			break;

		case AML_FIND_SET_RIGHT_BIT_OP:	/* find_set_right_bit (Operand, Result) */

			return_desc->integer.value = operand[0]->integer.value;

			/*
			 * The Acpi specification describes Integer type as a little
			 * endian unsigned value, so this boundary condition is valid.
			 */
			for (temp32 = 0; return_desc->integer.value &&
			     temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) {
				return_desc->integer.value <<= 1;
			}

			/* Since the bit position is one-based, subtract from 33 (65) */

			return_desc->integer.value =
			    temp32 ==
			    0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - temp32;
			break;

		case AML_FROM_BCD_OP:	/* from_bcd (BCDValue, Result) */

			/*
			 * The 64-bit ACPI integer can hold 16 4-bit BCD characters
			 * (if table is 32-bit, integer can hold 8 BCD characters)
			 * Convert each 4-bit BCD value
			 */
			power_of_ten = 1;
			return_desc->integer.value = 0;
			digit = operand[0]->integer.value;

			/* Convert each BCD digit (each is one nybble wide) */

			for (i = 0;
			     (i < acpi_gbl_integer_nybble_width) && (digit > 0);
			     i++) {

				/* Get the least significant 4-bit BCD digit */

				temp32 = ((u32) digit) & 0xF;

				/* Check the range of the digit */

				if (temp32 > 9) {
					ACPI_ERROR((AE_INFO,
						    "BCD digit too large (not decimal): 0x%X",
						    temp32));

					status = AE_AML_NUMERIC_OVERFLOW;
					goto cleanup;
				}

				/* Sum the digit into the result with the current power of 10 */

				return_desc->integer.value +=
				    (((acpi_integer) temp32) * power_of_ten);

				/* Shift to next BCD digit */

				digit >>= 4;

				/* Next power of 10 */

				power_of_ten *= 10;
			}
			break;

		case AML_TO_BCD_OP:	/* to_bcd (Operand, Result) */

			return_desc->integer.value = 0;
			digit = operand[0]->integer.value;

			/* Each BCD digit is one nybble wide */

			for (i = 0;
			     (i < acpi_gbl_integer_nybble_width) && (digit > 0);
			     i++) {
				(void)acpi_ut_short_divide(digit, 10, &digit,
							   &temp32);

				/*
				 * Insert the BCD digit that resides in the
				 * remainder from above
				 */
				return_desc->integer.value |=
				    (((acpi_integer) temp32) << ACPI_MUL_4(i));
			}

			/* Overflow if there is any data left in Digit */

			if (digit > 0) {
				ACPI_ERROR((AE_INFO,
					    "Integer too large to convert to BCD: %8.8X%8.8X",
					    ACPI_FORMAT_UINT64(operand[0]->
							       integer.value)));
				status = AE_AML_NUMERIC_OVERFLOW;
				goto cleanup;
			}
			break;

		case AML_COND_REF_OF_OP:	/* cond_ref_of (source_object, Result) */

			/*
			 * This op is a little strange because the internal return value is
			 * different than the return value stored in the result descriptor
			 * (There are really two return values)
			 */
			if ((struct acpi_namespace_node *)operand[0] ==
			    acpi_gbl_root_node) {
				/*
				 * This means that the object does not exist in the namespace,
				 * return FALSE
				 */
				return_desc->integer.value = 0;
				goto cleanup;
			}

			/* Get the object reference, store it, and remove our reference */

			status = acpi_ex_get_object_reference(operand[0],
							      &return_desc2,
							      walk_state);
			if (ACPI_FAILURE(status)) {
				goto cleanup;
			}

			status =
			    acpi_ex_store(return_desc2, operand[1], walk_state);
			acpi_ut_remove_reference(return_desc2);

			/* The object exists in the namespace, return TRUE */

			return_desc->integer.value = ACPI_INTEGER_MAX;
			goto cleanup;

		default:
			/* No other opcodes get here */
			break;
		}
		break;

	case AML_STORE_OP:	/* Store (Source, Target) */

		/*
		 * A store operand is typically a number, string, buffer or lvalue
		 * Be careful about deleting the source object,
		 * since the object itself may have been stored.
		 */
		status = acpi_ex_store(operand[0], operand[1], walk_state);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}

		/* It is possible that the Store already produced a return object */

		if (!walk_state->result_obj) {
			/*
			 * Normally, we would remove a reference on the Operand[0]
			 * parameter; But since it is being used as the internal return
			 * object (meaning we would normally increment it), the two
			 * cancel out, and we simply don't do anything.
			 */
			walk_state->result_obj = operand[0];
			walk_state->operands[0] = NULL;	/* Prevent deletion */
		}
		return_ACPI_STATUS(status);

		/*
		 * ACPI 2.0 Opcodes
		 */
	case AML_COPY_OP:	/* Copy (Source, Target) */

		status =
		    acpi_ut_copy_iobject_to_iobject(operand[0], &return_desc,
						    walk_state);
		break;

	case AML_TO_DECSTRING_OP:	/* to_decimal_string (Data, Result) */

		status = acpi_ex_convert_to_string(operand[0], &return_desc,
						   ACPI_EXPLICIT_CONVERT_DECIMAL);
		if (return_desc == operand[0]) {

			/* No conversion performed, add ref to handle return value */
			acpi_ut_add_reference(return_desc);
		}
		break;

	case AML_TO_HEXSTRING_OP:	/* to_hex_string (Data, Result) */

		status = acpi_ex_convert_to_string(operand[0], &return_desc,
						   ACPI_EXPLICIT_CONVERT_HEX);
		if (return_desc == operand[0]) {

			/* No conversion performed, add ref to handle return value */
			acpi_ut_add_reference(return_desc);
		}
		break;

	case AML_TO_BUFFER_OP:	/* to_buffer (Data, Result) */

		status = acpi_ex_convert_to_buffer(operand[0], &return_desc);
		if (return_desc == operand[0]) {

			/* No conversion performed, add ref to handle return value */
			acpi_ut_add_reference(return_desc);
		}
		break;

	case AML_TO_INTEGER_OP:	/* to_integer (Data, Result) */

		status = acpi_ex_convert_to_integer(operand[0], &return_desc,
						    ACPI_ANY_BASE);
		if (return_desc == operand[0]) {

			/* No conversion performed, add ref to handle return value */
			acpi_ut_add_reference(return_desc);
		}
		break;

	case AML_SHIFT_LEFT_BIT_OP:	/* shift_left_bit (Source, bit_num) */
	case AML_SHIFT_RIGHT_BIT_OP:	/* shift_right_bit (Source, bit_num) */

		/* These are two obsolete opcodes */

		ACPI_ERROR((AE_INFO,
			    "%s is obsolete and not implemented",
			    acpi_ps_get_opcode_name(walk_state->opcode)));
		status = AE_SUPPORT;
		goto cleanup;

	default:		/* Unknown opcode */

		ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
			    walk_state->opcode));
		status = AE_AML_BAD_OPCODE;
		goto cleanup;
	}

	if (ACPI_SUCCESS(status)) {

		/* Store the return value computed above into the target object */

		status = acpi_ex_store(return_desc, operand[1], walk_state);
	}

      cleanup:

	/* Delete return object on error */

	if (ACPI_FAILURE(status)) {
		acpi_ut_remove_reference(return_desc);
	}

	/* Save return object on success */

	else if (!walk_state->result_obj) {
		walk_state->result_obj = return_desc;
	}

	return_ACPI_STATUS(status);
}
acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state)
{
    union acpi_operand_object **operand = &walk_state->operands[0];
    union acpi_operand_object *return_desc = NULL;
    acpi_status status = AE_OK;
    acpi_integer index;
    union acpi_operand_object *this_element;

    ACPI_FUNCTION_TRACE_STR(ex_opcode_6A_0T_1R,
                            acpi_ps_get_opcode_name(walk_state->opcode));

    switch (walk_state->opcode) {
    case AML_MATCH_OP:
        /*
         * Match (search_pkg[0], match_op1[1], match_obj1[2],
         *                      match_op2[3], match_obj2[4], start_index[5])
         */

        /* Validate both Match Term Operators (MTR, MEQ, etc.) */

        if ((operand[1]->integer.value > MAX_MATCH_OPERATOR) ||
                (operand[3]->integer.value > MAX_MATCH_OPERATOR)) {
            ACPI_ERROR((AE_INFO, "Match operator out of range"));
            status = AE_AML_OPERAND_VALUE;
            goto cleanup;
        }

        /* Get the package start_index, validate against the package length */

        index = operand[5]->integer.value;
        if (index >= operand[0]->package.count) {
            ACPI_ERROR((AE_INFO,
                        "Index (%X%8.8X) beyond package end (%X)",
                        ACPI_FORMAT_UINT64(index),
                        operand[0]->package.count));
            status = AE_AML_PACKAGE_LIMIT;
            goto cleanup;
        }

        /* Create an integer for the return value */

        return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
        if (!return_desc) {
            status = AE_NO_MEMORY;
            goto cleanup;

        }

        /* Default return value if no match found */

        return_desc->integer.value = ACPI_INTEGER_MAX;

        /*
         * Examine each element until a match is found. Both match conditions
         * must be satisfied for a match to occur. Within the loop,
         * "continue" signifies that the current element does not match
         * and the next should be examined.
         *
         * Upon finding a match, the loop will terminate via "break" at
         * the bottom.  If it terminates "normally", match_value will be
         * ACPI_INTEGER_MAX (Ones) (its initial value) indicating that no
         * match was found.
         */
        for (; index < operand[0]->package.count; index++) {

            /* Get the current package element */

            this_element = operand[0]->package.elements[index];

            /* Treat any uninitialized (NULL) elements as non-matching */

            if (!this_element) {
                continue;
            }

            /*
             * Both match conditions must be satisfied. Execution of a continue
             * (proceed to next iteration of enclosing for loop) signifies a
             * non-match.
             */
            if (!acpi_ex_do_match((u32) operand[1]->integer.value,
                                  this_element, operand[2])) {
                continue;
            }

            if (!acpi_ex_do_match((u32) operand[3]->integer.value,
                                  this_element, operand[4])) {
                continue;
            }

            /* Match found: Index is the return value */

            return_desc->integer.value = index;
            break;
        }
        break;

    case AML_LOAD_TABLE_OP:

        status = acpi_ex_load_table_op(walk_state, &return_desc);
        break;

    default:

        ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
                    walk_state->opcode));
        status = AE_AML_BAD_OPCODE;
        goto cleanup;
    }

    walk_state->result_obj = return_desc;

cleanup:

    /* Delete return object on error */

    if (ACPI_FAILURE(status)) {
        acpi_ut_remove_reference(return_desc);
    }

    return_ACPI_STATUS(status);
}
Example #27
0
acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
{
	union acpi_operand_object **operand = &walk_state->operands[0];
	union acpi_operand_object *temp_desc;
	union acpi_operand_object *return_desc = NULL;
	acpi_status status = AE_OK;
	u32 type;
	acpi_integer value;

	ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_0T_1R,
				acpi_ps_get_opcode_name(walk_state->opcode));

	/* Examine the AML opcode */

	switch (walk_state->opcode) {
	case AML_LNOT_OP:	/* LNot (Operand) */

		return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
		if (!return_desc) {
			status = AE_NO_MEMORY;
			goto cleanup;
		}

		/*
		 * Set result to ONES (TRUE) if Value == 0.  Note:
		 * return_desc->Integer.Value is initially == 0 (FALSE) from above.
		 */
		if (!operand[0]->integer.value) {
			return_desc->integer.value = ACPI_INTEGER_MAX;
		}
		break;

	case AML_DECREMENT_OP:	/* Decrement (Operand)  */
	case AML_INCREMENT_OP:	/* Increment (Operand)  */

		/*
		 * Create a new integer.  Can't just get the base integer and
		 * increment it because it may be an Arg or Field.
		 */
		return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
		if (!return_desc) {
			status = AE_NO_MEMORY;
			goto cleanup;
		}

		/*
		 * Since we are expecting a Reference operand, it can be either a
		 * NS Node or an internal object.
		 */
		temp_desc = operand[0];
		if (ACPI_GET_DESCRIPTOR_TYPE(temp_desc) ==
		    ACPI_DESC_TYPE_OPERAND) {

			/* Internal reference object - prevent deletion */

			acpi_ut_add_reference(temp_desc);
		}

		/*
		 * Convert the Reference operand to an Integer (This removes a
		 * reference on the Operand[0] object)
		 *
		 * NOTE:  We use LNOT_OP here in order to force resolution of the
		 * reference operand to an actual integer.
		 */
		status =
		    acpi_ex_resolve_operands(AML_LNOT_OP, &temp_desc,
					     walk_state);
		if (ACPI_FAILURE(status)) {
			ACPI_EXCEPTION((AE_INFO, status,
					"While resolving operands for [%s]",
					acpi_ps_get_opcode_name(walk_state->
								opcode)));

			goto cleanup;
		}

		/*
		 * temp_desc is now guaranteed to be an Integer object --
		 * Perform the actual increment or decrement
		 */
		if (walk_state->opcode == AML_INCREMENT_OP) {
			return_desc->integer.value =
			    temp_desc->integer.value + 1;
		} else {
			return_desc->integer.value =
			    temp_desc->integer.value - 1;
		}

		/* Finished with this Integer object */

		acpi_ut_remove_reference(temp_desc);

		/*
		 * Store the result back (indirectly) through the original
		 * Reference object
		 */
		status = acpi_ex_store(return_desc, operand[0], walk_state);
		break;

	case AML_TYPE_OP:	/* object_type (source_object) */

		/*
		 * Note: The operand is not resolved at this point because we want to
		 * get the associated object, not its value.  For example, we don't
		 * want to resolve a field_unit to its value, we want the actual
		 * field_unit object.
		 */

		/* Get the type of the base object */

		status =
		    acpi_ex_resolve_multiple(walk_state, operand[0], &type,
					     NULL);
		if (ACPI_FAILURE(status)) {
			goto cleanup;
		}

		/* Allocate a descriptor to hold the type. */

		return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
		if (!return_desc) {
			status = AE_NO_MEMORY;
			goto cleanup;
		}

		return_desc->integer.value = type;
		break;

	case AML_SIZE_OF_OP:	/* size_of (source_object) */

		/*
		 * Note: The operand is not resolved at this point because we want to
		 * get the associated object, not its value.
		 */

		/* Get the base object */

		status = acpi_ex_resolve_multiple(walk_state,
						  operand[0], &type,
						  &temp_desc);
		if (ACPI_FAILURE(status)) {
			goto cleanup;
		}

		/*
		 * The type of the base object must be integer, buffer, string, or
		 * package.  All others are not supported.
		 *
		 * NOTE: Integer is not specifically supported by the ACPI spec,
		 * but is supported implicitly via implicit operand conversion.
		 * rather than bother with conversion, we just use the byte width
		 * global (4 or 8 bytes).
		 */
		switch (type) {
		case ACPI_TYPE_INTEGER:
			value = acpi_gbl_integer_byte_width;
			break;

		case ACPI_TYPE_BUFFER:
			value = temp_desc->buffer.length;
			break;

		case ACPI_TYPE_STRING:
			value = temp_desc->string.length;
			break;

		case ACPI_TYPE_PACKAGE:
			value = temp_desc->package.count;
			break;

		default:
			ACPI_ERROR((AE_INFO,
				    "Operand is not Buf/Int/Str/Pkg - found type %s",
				    acpi_ut_get_type_name(type)));
			status = AE_AML_OPERAND_TYPE;
			goto cleanup;
		}

		/*
		 * Now that we have the size of the object, create a result
		 * object to hold the value
		 */
		return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
		if (!return_desc) {
			status = AE_NO_MEMORY;
			goto cleanup;
		}

		return_desc->integer.value = value;
		break;

	case AML_REF_OF_OP:	/* ref_of (source_object) */

		status =
		    acpi_ex_get_object_reference(operand[0], &return_desc,
						 walk_state);
		if (ACPI_FAILURE(status)) {
			goto cleanup;
		}
		break;

	case AML_DEREF_OF_OP:	/* deref_of (obj_reference | String) */

		/* Check for a method local or argument, or standalone String */

		if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) ==
		    ACPI_DESC_TYPE_NAMED) {
			temp_desc =
			    acpi_ns_get_attached_object((struct
							 acpi_namespace_node *)
							operand[0]);
			if (temp_desc
			    &&
			    ((ACPI_GET_OBJECT_TYPE(temp_desc) ==
			      ACPI_TYPE_STRING)
			     || (ACPI_GET_OBJECT_TYPE(temp_desc) ==
				 ACPI_TYPE_LOCAL_REFERENCE))) {
				operand[0] = temp_desc;
				acpi_ut_add_reference(temp_desc);
			} else {
				status = AE_AML_OPERAND_TYPE;
				goto cleanup;
			}
		} else {
			switch (ACPI_GET_OBJECT_TYPE(operand[0])) {
			case ACPI_TYPE_LOCAL_REFERENCE:
				/*
				 * This is a deref_of (local_x | arg_x)
				 *
				 * Must resolve/dereference the local/arg reference first
				 */
				switch (operand[0]->reference.opcode) {
				case AML_LOCAL_OP:
				case AML_ARG_OP:

					/* Set Operand[0] to the value of the local/arg */

					status =
					    acpi_ds_method_data_get_value
					    (operand[0]->reference.opcode,
					     operand[0]->reference.offset,
					     walk_state, &temp_desc);
					if (ACPI_FAILURE(status)) {
						goto cleanup;
					}

					/*
					 * Delete our reference to the input object and
					 * point to the object just retrieved
					 */
					acpi_ut_remove_reference(operand[0]);
					operand[0] = temp_desc;
					break;

				case AML_REF_OF_OP:

					/* Get the object to which the reference refers */

					temp_desc =
					    operand[0]->reference.object;
					acpi_ut_remove_reference(operand[0]);
					operand[0] = temp_desc;
					break;

				default:

					/* Must be an Index op - handled below */
					break;
				}
				break;

			case ACPI_TYPE_STRING:
				break;

			default:
				status = AE_AML_OPERAND_TYPE;
				goto cleanup;
			}
		}

		if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) !=
		    ACPI_DESC_TYPE_NAMED) {
			if (ACPI_GET_OBJECT_TYPE(operand[0]) ==
			    ACPI_TYPE_STRING) {
				/*
				 * This is a deref_of (String). The string is a reference
				 * to a named ACPI object.
				 *
				 * 1) Find the owning Node
				 * 2) Dereference the node to an actual object. Could be a
				 *    Field, so we need to resolve the node to a value.
				 */
				status =
				    acpi_ns_get_node(walk_state->scope_info->
						     scope.node,
						     operand[0]->string.pointer,
						     ACPI_NS_SEARCH_PARENT,
						     ACPI_CAST_INDIRECT_PTR
						     (struct
						      acpi_namespace_node,
						      &return_desc));
				if (ACPI_FAILURE(status)) {
					goto cleanup;
				}

				status =
				    acpi_ex_resolve_node_to_value
				    (ACPI_CAST_INDIRECT_PTR
				     (struct acpi_namespace_node, &return_desc),
				     walk_state);
				goto cleanup;
			}
		}

		/* Operand[0] may have changed from the code above */

		if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) ==
		    ACPI_DESC_TYPE_NAMED) {
			/*
			 * This is a deref_of (object_reference)
			 * Get the actual object from the Node (This is the dereference).
			 * This case may only happen when a local_x or arg_x is
			 * dereferenced above.
			 */
			return_desc = acpi_ns_get_attached_object((struct
								   acpi_namespace_node
								   *)
								  operand[0]);
			acpi_ut_add_reference(return_desc);
		} else {
			/*
			 * This must be a reference object produced by either the
			 * Index() or ref_of() operator
			 */
			switch (operand[0]->reference.opcode) {
			case AML_INDEX_OP:

				/*
				 * The target type for the Index operator must be
				 * either a Buffer or a Package
				 */
				switch (operand[0]->reference.target_type) {
				case ACPI_TYPE_BUFFER_FIELD:

					temp_desc =
					    operand[0]->reference.object;

					/*
					 * Create a new object that contains one element of the
					 * buffer -- the element pointed to by the index.
					 *
					 * NOTE: index into a buffer is NOT a pointer to a
					 * sub-buffer of the main buffer, it is only a pointer to a
					 * single element (byte) of the buffer!
					 */
					return_desc =
					    acpi_ut_create_internal_object
					    (ACPI_TYPE_INTEGER);
					if (!return_desc) {
						status = AE_NO_MEMORY;
						goto cleanup;
					}

					/*
					 * Since we are returning the value of the buffer at the
					 * indexed location, we don't need to add an additional
					 * reference to the buffer itself.
					 */
					return_desc->integer.value =
					    temp_desc->buffer.
					    pointer[operand[0]->reference.
						    offset];
					break;

				case ACPI_TYPE_PACKAGE:

					/*
					 * Return the referenced element of the package.  We must
					 * add another reference to the referenced object, however.
					 */
					return_desc =
					    *(operand[0]->reference.where);
					if (return_desc) {
						acpi_ut_add_reference
						    (return_desc);
					}
					break;

				default:

					ACPI_ERROR((AE_INFO,
						    "Unknown Index TargetType %X in obj %p",
						    operand[0]->reference.
						    target_type, operand[0]));
					status = AE_AML_OPERAND_TYPE;
					goto cleanup;
				}
				break;

			case AML_REF_OF_OP:

				return_desc = operand[0]->reference.object;

				if (ACPI_GET_DESCRIPTOR_TYPE(return_desc) ==
				    ACPI_DESC_TYPE_NAMED) {
					return_desc =
					    acpi_ns_get_attached_object((struct
									 acpi_namespace_node
									 *)
									return_desc);
				}

				/* Add another reference to the object! */

				acpi_ut_add_reference(return_desc);
				break;

			default:
				ACPI_ERROR((AE_INFO,
					    "Unknown opcode in reference(%p) - %X",
					    operand[0],
					    operand[0]->reference.opcode));

				status = AE_TYPE;
				goto cleanup;
			}
		}
		break;

	default:

		ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
			    walk_state->opcode));
		status = AE_AML_BAD_OPCODE;
		goto cleanup;
	}