コード例 #1
0
ファイル: dsmthdat.c プロジェクト: jhbsz/MI424WR_GEN2_Rev_E-F
acpi_status
acpi_ds_method_data_set_entry (
    u16                     opcode,
    u32                     index,
    acpi_operand_object     *object,
    acpi_walk_state         *walk_state)
{
    acpi_status             status;
    acpi_operand_object     **entry;


    FUNCTION_TRACE ("Ds_method_data_set_entry");


    /* Get a pointer to the stack entry to set */

    status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry);
    if (ACPI_FAILURE (status)) {
        return_ACPI_STATUS (status);
    }

    /* Increment ref count so object can't be deleted while installed */

    acpi_ut_add_reference (object);

    /* Install the object into the stack entry */

    *entry = object;

    return_ACPI_STATUS (AE_OK);
}
コード例 #2
0
ファイル: evregion.c プロジェクト: ravi-vid/linux-xlnx
acpi_status
acpi_ev_attach_region(union acpi_operand_object *handler_obj,
                      union acpi_operand_object *region_obj,
                      u8 acpi_ns_is_locked)
{

    ACPI_FUNCTION_TRACE(ev_attach_region);

    ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
                      "Adding Region [%4.4s] %p to address handler %p [%s]\n",
                      acpi_ut_get_node_name(region_obj->region.node),
                      region_obj, handler_obj,
                      acpi_ut_get_region_name(region_obj->region.
                              space_id)));

    /* Link this region to the front of the handler's list */

    region_obj->region.next = handler_obj->address_space.region_list;
    handler_obj->address_space.region_list = region_obj;

    /* Install the region's handler */

    if (region_obj->region.handler) {
        return_ACPI_STATUS(AE_ALREADY_EXISTS);
    }

    region_obj->region.handler = handler_obj;
    acpi_ut_add_reference(handler_obj);

    return_ACPI_STATUS(AE_OK);
}
コード例 #3
0
acpi_status
acpi_ev_attach_region (
	union acpi_operand_object       *handler_obj,
	union acpi_operand_object       *region_obj,
	u8                              acpi_ns_is_locked)
{
	acpi_status                     status;
	acpi_status                     status2;


	ACPI_FUNCTION_TRACE ("ev_attach_region");


	ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
		"Adding Region %p to address handler %p [%s]\n",
		region_obj, handler_obj, acpi_ut_get_region_name (region_obj->region.space_id)));


	/* Link this region to the front of the handler's list */

	region_obj->region.next = handler_obj->address_space.region_list;
	handler_obj->address_space.region_list = region_obj;

	/* Install the region's handler */

	if (region_obj->region.address_space) {
		return_ACPI_STATUS (AE_ALREADY_EXISTS);
	}

	region_obj->region.address_space = handler_obj;
	acpi_ut_add_reference (handler_obj);

	/*
	 * Tell all users that this region is usable by running the _REG
	 * method
	 */
	if (acpi_ns_is_locked) {
		status2 = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
		if (ACPI_FAILURE (status2)) {
			return_ACPI_STATUS (status2);
		}
	}

	status = acpi_ev_execute_reg_method (region_obj, 1);

	if (acpi_ns_is_locked) {
		status2 = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
		if (ACPI_FAILURE (status2)) {
			return_ACPI_STATUS (status2);
		}
	}

	return_ACPI_STATUS (status);
}
コード例 #4
0
ファイル: nsxfeval.c プロジェクト: AshishNamdev/linux
/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_resolve_references
 *
 * PARAMETERS:  info                    - Evaluation info block
 *
 * RETURN:      Info->return_object is replaced with the dereferenced object
 *
 * DESCRIPTION: Dereference certain reference objects. Called before an
 *              internal return object is converted to an external union acpi_object.
 *
 * Performs an automatic dereference of Index and ref_of reference objects.
 * These reference objects are not supported by the union acpi_object, so this is a
 * last resort effort to return something useful. Also, provides compatibility
 * with other ACPI implementations.
 *
 * NOTE: does not handle references within returned package objects or nested
 * references, but this support could be added later if found to be necessary.
 *
 ******************************************************************************/
static void acpi_ns_resolve_references(struct acpi_evaluate_info *info)
{
	union acpi_operand_object *obj_desc = NULL;
	struct acpi_namespace_node *node;

	/* We are interested in reference objects only */

	if ((info->return_object)->common.type != ACPI_TYPE_LOCAL_REFERENCE) {
		return;
	}

	/*
	 * Two types of references are supported - those created by Index and
	 * ref_of operators. A name reference (AML_NAMEPATH_OP) can be converted
	 * to an union acpi_object, so it is not dereferenced here. A ddb_handle
	 * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to
	 * an union acpi_object.
	 */
	switch (info->return_object->reference.class) {
	case ACPI_REFCLASS_INDEX:

		obj_desc = *(info->return_object->reference.where);
		break;

	case ACPI_REFCLASS_REFOF:

		node = info->return_object->reference.object;
		if (node) {
			obj_desc = node->object;
		}
		break;

	default:

		return;
	}

	/* Replace the existing reference object */

	if (obj_desc) {
		acpi_ut_add_reference(obj_desc);
		acpi_ut_remove_reference(info->return_object);
		info->return_object = obj_desc;
	}

	return;
}
コード例 #5
0
ファイル: dsmthdat.c プロジェクト: GodFox/magx_kernel_xpixl
acpi_status
acpi_ds_method_data_set_value (
	u16                             opcode,
	u32                             index,
	union acpi_operand_object       *object,
	struct acpi_walk_state          *walk_state)
{
	acpi_status                     status;
	struct acpi_namespace_node      *node;


	ACPI_FUNCTION_TRACE ("ds_method_data_set_value");


	ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
		"new_obj %p Opcode %X, Refs=%d [%s]\n", object,
		opcode, object->common.reference_count,
		acpi_ut_get_type_name (object->common.type)));

	/* Get the namespace node for the arg/local */

	status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node);
	if (ACPI_FAILURE (status)) {
		return_ACPI_STATUS (status);
	}

	/*
	 * Increment ref count so object can't be deleted while installed.
	 * NOTE: We do not copy the object in order to preserve the call by
	 * reference semantics of ACPI Control Method invocation.
	 * (See ACPI specification 2.0_c)
	 */
	acpi_ut_add_reference (object);

	/* Install the object */

	node->object = object;
	return_ACPI_STATUS (status);
}
コード例 #6
0
acpi_status
acpi_ex_prep_field_value (
	struct acpi_create_field_info   *info)
{
	union acpi_operand_object       *obj_desc;
	u32                             type;
	acpi_status                     status;


	ACPI_FUNCTION_TRACE ("ex_prep_field_value");


	/* Parameter validation */

	if (info->field_type != ACPI_TYPE_LOCAL_INDEX_FIELD) {
		if (!info->region_node) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null region_node\n"));
			return_ACPI_STATUS (AE_AML_NO_OPERAND);
		}

		type = acpi_ns_get_type (info->region_node);
		if (type != ACPI_TYPE_REGION) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
				"Needed Region, found type %X %s\n",
				type, acpi_ut_get_type_name (type)));

			return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
		}
	}

	/* Allocate a new field object */

	obj_desc = acpi_ut_create_internal_object (info->field_type);
	if (!obj_desc) {
		return_ACPI_STATUS (AE_NO_MEMORY);
	}

	/* Initialize areas of the object that are common to all fields */

	obj_desc->common_field.node = info->field_node;
	status = acpi_ex_prep_common_field_object (obj_desc, info->field_flags,
			 info->attribute, info->field_bit_position, info->field_bit_length);
	if (ACPI_FAILURE (status)) {
		acpi_ut_delete_object_desc (obj_desc);
		return_ACPI_STATUS (status);
	}

	/* Initialize areas of the object that are specific to the field type */

	switch (info->field_type) {
	case ACPI_TYPE_LOCAL_REGION_FIELD:

		obj_desc->field.region_obj   = acpi_ns_get_attached_object (info->region_node);

		/* An additional reference for the container */

		acpi_ut_add_reference (obj_desc->field.region_obj);

		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
			"region_field: Bitoff=%X Off=%X Gran=%X Region %p\n",
			obj_desc->field.start_field_bit_offset, obj_desc->field.base_byte_offset,
			obj_desc->field.access_byte_width, obj_desc->field.region_obj));
		break;


	case ACPI_TYPE_LOCAL_BANK_FIELD:

		obj_desc->bank_field.value   = info->bank_value;
		obj_desc->bank_field.region_obj = acpi_ns_get_attached_object (info->region_node);
		obj_desc->bank_field.bank_obj = acpi_ns_get_attached_object (info->register_node);

		/* An additional reference for the attached objects */

		acpi_ut_add_reference (obj_desc->bank_field.region_obj);
		acpi_ut_add_reference (obj_desc->bank_field.bank_obj);

		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
			"Bank Field: bit_off=%X Off=%X Gran=%X Region %p bank_reg %p\n",
			obj_desc->bank_field.start_field_bit_offset,
			obj_desc->bank_field.base_byte_offset,
			obj_desc->field.access_byte_width,
			obj_desc->bank_field.region_obj,
			obj_desc->bank_field.bank_obj));
		break;


	case ACPI_TYPE_LOCAL_INDEX_FIELD:

		obj_desc->index_field.index_obj = acpi_ns_get_attached_object (info->register_node);
		obj_desc->index_field.data_obj = acpi_ns_get_attached_object (info->data_register_node);
		obj_desc->index_field.value  = (u32)
			(info->field_bit_position / ACPI_MUL_8 (obj_desc->field.access_byte_width));

		if (!obj_desc->index_field.data_obj || !obj_desc->index_field.index_obj) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Index Object\n"));
			return_ACPI_STATUS (AE_AML_INTERNAL);
		}

		/* An additional reference for the attached objects */

		acpi_ut_add_reference (obj_desc->index_field.data_obj);
		acpi_ut_add_reference (obj_desc->index_field.index_obj);

		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
			"index_field: bitoff=%X off=%X gran=%X Index %p Data %p\n",
			obj_desc->index_field.start_field_bit_offset,
			obj_desc->index_field.base_byte_offset,
			obj_desc->field.access_byte_width,
			obj_desc->index_field.index_obj,
			obj_desc->index_field.data_obj));
		break;

	default:
		/* No other types should get here */
		break;
	}

	/*
	 * Store the constructed descriptor (obj_desc) into the parent Node,
	 * preserving the current type of that named_obj.
	 */
	status = acpi_ns_attach_object (info->field_node, obj_desc,
			  acpi_ns_get_type (info->field_node));

	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "set named_obj %p (%4.4s) val = %p\n",
			info->field_node, info->field_node->name.ascii, obj_desc));

	/* Remove local reference to the object */

	acpi_ut_remove_reference (obj_desc);
	return_ACPI_STATUS (status);
}
コード例 #7
0
ファイル: exprep.c プロジェクト: 1703011/asuswrt-merlin
acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
{
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *second_desc = NULL;
	u32 type;
	acpi_status status;

	ACPI_FUNCTION_TRACE(ex_prep_field_value);

	/* Parameter validation */

	if (info->field_type != ACPI_TYPE_LOCAL_INDEX_FIELD) {
		if (!info->region_node) {
			ACPI_ERROR((AE_INFO, "Null RegionNode"));
			return_ACPI_STATUS(AE_AML_NO_OPERAND);
		}

		type = acpi_ns_get_type(info->region_node);
		if (type != ACPI_TYPE_REGION) {
			ACPI_ERROR((AE_INFO,
				    "Needed Region, found type 0x%X (%s)",
				    type, acpi_ut_get_type_name(type)));

			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
		}
	}

	/* Allocate a new field object */

	obj_desc = acpi_ut_create_internal_object(info->field_type);
	if (!obj_desc) {
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	/* Initialize areas of the object that are common to all fields */

	obj_desc->common_field.node = info->field_node;
	status = acpi_ex_prep_common_field_object(obj_desc, info->field_flags,
						  info->attribute,
						  info->field_bit_position,
						  info->field_bit_length);
	if (ACPI_FAILURE(status)) {
		acpi_ut_delete_object_desc(obj_desc);
		return_ACPI_STATUS(status);
	}

	/* Initialize areas of the object that are specific to the field type */

	switch (info->field_type) {
	case ACPI_TYPE_LOCAL_REGION_FIELD:

		obj_desc->field.region_obj =
		    acpi_ns_get_attached_object(info->region_node);

		/* An additional reference for the container */

		acpi_ut_add_reference(obj_desc->field.region_obj);

		/* allow full data read from EC address space */
		if (obj_desc->field.region_obj->region.space_id ==
			ACPI_ADR_SPACE_EC) {
			if (obj_desc->common_field.bit_length > 8) {
				unsigned width =
					ACPI_ROUND_BITS_UP_TO_BYTES(
					obj_desc->common_field.bit_length);
				// access_bit_width is u8, don't overflow it
				if (width > 8)
					width = 8;
				obj_desc->common_field.access_byte_width =
							width;
				obj_desc->common_field.access_bit_width =
							8 * width;
			}
		}

		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
				  "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n",
				  obj_desc->field.start_field_bit_offset,
				  obj_desc->field.base_byte_offset,
				  obj_desc->field.access_byte_width,
				  obj_desc->field.region_obj));
		break;

	case ACPI_TYPE_LOCAL_BANK_FIELD:

		obj_desc->bank_field.value = info->bank_value;
		obj_desc->bank_field.region_obj =
		    acpi_ns_get_attached_object(info->region_node);
		obj_desc->bank_field.bank_obj =
		    acpi_ns_get_attached_object(info->register_node);

		/* An additional reference for the attached objects */

		acpi_ut_add_reference(obj_desc->bank_field.region_obj);
		acpi_ut_add_reference(obj_desc->bank_field.bank_obj);

		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
				  "Bank Field: BitOff %X, Off %X, Gran %X, Region %p, BankReg %p\n",
				  obj_desc->bank_field.start_field_bit_offset,
				  obj_desc->bank_field.base_byte_offset,
				  obj_desc->field.access_byte_width,
				  obj_desc->bank_field.region_obj,
				  obj_desc->bank_field.bank_obj));

		/*
		 * Remember location in AML stream of the field unit
		 * opcode and operands -- since the bank_value
		 * operands must be evaluated.
		 */
		second_desc = obj_desc->common.next_object;
		second_desc->extra.aml_start =
		    ACPI_CAST_PTR(union acpi_parse_object,
				  info->data_register_node)->named.data;
		second_desc->extra.aml_length =
		    ACPI_CAST_PTR(union acpi_parse_object,
				  info->data_register_node)->named.length;

		break;

	case ACPI_TYPE_LOCAL_INDEX_FIELD:

		/* Get the Index and Data registers */

		obj_desc->index_field.index_obj =
		    acpi_ns_get_attached_object(info->register_node);
		obj_desc->index_field.data_obj =
		    acpi_ns_get_attached_object(info->data_register_node);

		if (!obj_desc->index_field.data_obj
		    || !obj_desc->index_field.index_obj) {
			ACPI_ERROR((AE_INFO,
				    "Null Index Object during field prep"));
			acpi_ut_delete_object_desc(obj_desc);
			return_ACPI_STATUS(AE_AML_INTERNAL);
		}

		/* An additional reference for the attached objects */

		acpi_ut_add_reference(obj_desc->index_field.data_obj);
		acpi_ut_add_reference(obj_desc->index_field.index_obj);

		/*
		 * April 2006: Changed to match MS behavior
		 *
		 * The value written to the Index register is the byte offset of the
		 * target field in units of the granularity of the index_field
		 *
		 * Previously, the value was calculated as an index in terms of the
		 * width of the Data register, as below:
		 *
		 *      obj_desc->index_field.Value = (u32)
		 *          (Info->field_bit_position / ACPI_MUL_8 (
		 *              obj_desc->Field.access_byte_width));
		 *
		 * February 2006: Tried value as a byte offset:
		 *      obj_desc->index_field.Value = (u32)
		 *          ACPI_DIV_8 (Info->field_bit_position);
		 */
		obj_desc->index_field.value =
		    (u32) ACPI_ROUND_DOWN(ACPI_DIV_8(info->field_bit_position),
					  obj_desc->index_field.
					  access_byte_width);

		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
				  "IndexField: BitOff %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n",
				  obj_desc->index_field.start_field_bit_offset,
				  obj_desc->index_field.base_byte_offset,
				  obj_desc->index_field.value,
				  obj_desc->field.access_byte_width,
				  obj_desc->index_field.index_obj,
				  obj_desc->index_field.data_obj));
		break;

	default:
		/* No other types should get here */
		break;
	}

	/*
	 * Store the constructed descriptor (obj_desc) into the parent Node,
	 * preserving the current type of that named_obj.
	 */
	status = acpi_ns_attach_object(info->field_node, obj_desc,
				       acpi_ns_get_type(info->field_node));

	ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
			  "Set NamedObj %p [%4.4s], ObjDesc %p\n",
			  info->field_node,
			  acpi_ut_get_node_name(info->field_node), obj_desc));

	/* Remove local reference to the object */

	acpi_ut_remove_reference(obj_desc);
	return_ACPI_STATUS(status);
}
コード例 #8
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_install_notify_handler
 *
 * PARAMETERS:  Device          - The device for which notifies will be handled
 *              handler_type    - The type of handler:
 *                                  ACPI_SYSTEM_NOTIFY: system_handler (00-7f)
 *                                  ACPI_DEVICE_NOTIFY: driver_handler (80-ff)
 *                                  ACPI_ALL_NOTIFY:  both system and device
 *              Handler         - Address of the handler
 *              Context         - Value passed to the handler on each GPE
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Install a handler for notifies on an ACPI device
 *
 ******************************************************************************/
acpi_status
acpi_install_notify_handler(acpi_handle device,
			    u32 handler_type,
			    acpi_notify_handler handler, void *context)
{
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *notify_obj;
	struct acpi_namespace_node *node;
	acpi_status status;

	ACPI_FUNCTION_TRACE(acpi_install_notify_handler);

	/* Parameter validation */

	if ((!device) ||
	    (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Convert and validate the device handle */

	node = acpi_ns_validate_handle(device);
	if (!node) {
		status = AE_BAD_PARAMETER;
		goto unlock_and_exit;
	}

	/*
	 * Root Object:
	 * Registering a notify handler on the root object indicates that the
	 * caller wishes to receive notifications for all objects. Note that
	 * only one <external> global handler can be regsitered (per notify type).
	 */
	if (device == ACPI_ROOT_OBJECT) {

		/* Make sure the handler is not already installed */

		if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
		     acpi_gbl_system_notify.handler) ||
		    ((handler_type & ACPI_DEVICE_NOTIFY) &&
		     acpi_gbl_device_notify.handler)) {
			status = AE_ALREADY_EXISTS;
			goto unlock_and_exit;
		}

		if (handler_type & ACPI_SYSTEM_NOTIFY) {
			acpi_gbl_system_notify.node = node;
			acpi_gbl_system_notify.handler = handler;
			acpi_gbl_system_notify.context = context;
		}

		if (handler_type & ACPI_DEVICE_NOTIFY) {
			acpi_gbl_device_notify.node = node;
			acpi_gbl_device_notify.handler = handler;
			acpi_gbl_device_notify.context = context;
		}

		/* Global notify handler installed */
	}

	/*
	 * All Other Objects:
	 * Caller will only receive notifications specific to the target object.
	 * Note that only certain object types can receive notifications.
	 */
	else {
		/* Notifies allowed on this object? */

		if (!acpi_ev_is_notify_object(node)) {
			status = AE_TYPE;
			goto unlock_and_exit;
		}

		/* Check for an existing internal object */

		obj_desc = acpi_ns_get_attached_object(node);
		if (obj_desc) {

			/* Object exists - make sure there's no handler */

			if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
			     obj_desc->common_notify.system_notify) ||
			    ((handler_type & ACPI_DEVICE_NOTIFY) &&
			     obj_desc->common_notify.device_notify)) {
				status = AE_ALREADY_EXISTS;
				goto unlock_and_exit;
			}
		} else {
			/* Create a new object */

			obj_desc = acpi_ut_create_internal_object(node->type);
			if (!obj_desc) {
				status = AE_NO_MEMORY;
				goto unlock_and_exit;
			}

			/* Attach new object to the Node */

			status =
			    acpi_ns_attach_object(device, obj_desc, node->type);

			/* Remove local reference to the object */

			acpi_ut_remove_reference(obj_desc);
			if (ACPI_FAILURE(status)) {
				goto unlock_and_exit;
			}
		}

		/* Install the handler */

		notify_obj =
		    acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY);
		if (!notify_obj) {
			status = AE_NO_MEMORY;
			goto unlock_and_exit;
		}

		notify_obj->notify.node = node;
		notify_obj->notify.handler = handler;
		notify_obj->notify.context = context;

		if (handler_type & ACPI_SYSTEM_NOTIFY) {
			obj_desc->common_notify.system_notify = notify_obj;
		}

		if (handler_type & ACPI_DEVICE_NOTIFY) {
			obj_desc->common_notify.device_notify = notify_obj;
		}

		if (handler_type == ACPI_ALL_NOTIFY) {

			/* Extra ref if installed in both */

			acpi_ut_add_reference(notify_obj);
		}
	}

      unlock_and_exit:
	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
	return_ACPI_STATUS(status);
}
コード例 #9
0
ファイル: exstore.c プロジェクト: 3sOx/asuswrt-merlin
static acpi_status
acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
			      union acpi_operand_object *index_desc,
			      struct acpi_walk_state *walk_state)
{
	acpi_status status = AE_OK;
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *new_desc;
	u8 value = 0;
	u32 i;

	ACPI_FUNCTION_TRACE(ex_store_object_to_index);

	/*
	 * Destination must be a reference pointer, and
	 * must point to either a buffer or a package
	 */
	switch (index_desc->reference.target_type) {
	case ACPI_TYPE_PACKAGE:
		/*
		 * Storing to a package element. Copy the object and replace
		 * any existing object with the new object. No implicit
		 * conversion is performed.
		 *
		 * The object at *(index_desc->Reference.Where) is the
		 * element within the package that is to be modified.
		 * The parent package object is at index_desc->Reference.Object
		 */
		obj_desc = *(index_desc->reference.where);

		status =
		    acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc,
						    walk_state);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}

		if (obj_desc) {

			/* Decrement reference count by the ref count of the parent package */

			for (i = 0; i < ((union acpi_operand_object *)
					 index_desc->reference.object)->common.
			     reference_count; i++) {
				acpi_ut_remove_reference(obj_desc);
			}
		}

		*(index_desc->reference.where) = new_desc;

		/* Increment ref count by the ref count of the parent package-1 */

		for (i = 1; i < ((union acpi_operand_object *)
				 index_desc->reference.object)->common.
		     reference_count; i++) {
			acpi_ut_add_reference(new_desc);
		}

		break;

	case ACPI_TYPE_BUFFER_FIELD:

		/*
		 * Store into a Buffer or String (not actually a real buffer_field)
		 * at a location defined by an Index.
		 *
		 * The first 8-bit element of the source object is written to the
		 * 8-bit Buffer location defined by the Index destination object,
		 * according to the ACPI 2.0 specification.
		 */

		/*
		 * Make sure the target is a Buffer or String. An error should
		 * not happen here, since the reference_object was constructed
		 * by the INDEX_OP code.
		 */
		obj_desc = index_desc->reference.object;
		if ((ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_BUFFER) &&
		    (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_STRING)) {
			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
		}

		/*
		 * The assignment of the individual elements will be slightly
		 * different for each source type.
		 */
		switch (ACPI_GET_OBJECT_TYPE(source_desc)) {
		case ACPI_TYPE_INTEGER:

			/* Use the least-significant byte of the integer */

			value = (u8) (source_desc->integer.value);
			break;

		case ACPI_TYPE_BUFFER:
		case ACPI_TYPE_STRING:

			/* Note: Takes advantage of common string/buffer fields */

			value = source_desc->buffer.pointer[0];
			break;

		default:

			/* All other types are invalid */

			ACPI_ERROR((AE_INFO,
				    "Source must be Integer/Buffer/String type, not %s",
				    acpi_ut_get_object_type_name(source_desc)));
			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
		}

		/* Store the source value into the target buffer byte */

		obj_desc->buffer.pointer[index_desc->reference.offset] = value;
		break;

	default:
		ACPI_ERROR((AE_INFO, "Target is not a Package or BufferField"));
		status = AE_AML_OPERAND_TYPE;
		break;
	}

	return_ACPI_STATUS(status);
}
コード例 #10
0
acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
{
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *second_desc = NULL;
	acpi_status status;
	u32 access_byte_width;
	u32 type;

	ACPI_FUNCTION_TRACE(ex_prep_field_value);

	/*                      */

	if (info->field_type != ACPI_TYPE_LOCAL_INDEX_FIELD) {
		if (!info->region_node) {
			ACPI_ERROR((AE_INFO, "Null RegionNode"));
			return_ACPI_STATUS(AE_AML_NO_OPERAND);
		}

		type = acpi_ns_get_type(info->region_node);
		if (type != ACPI_TYPE_REGION) {
			ACPI_ERROR((AE_INFO,
				    "Needed Region, found type 0x%X (%s)", type,
				    acpi_ut_get_type_name(type)));

			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
		}
	}

	/*                             */

	obj_desc = acpi_ut_create_internal_object(info->field_type);
	if (!obj_desc) {
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	/*                                                              */

	obj_desc->common_field.node = info->field_node;
	status = acpi_ex_prep_common_field_object(obj_desc,
						  info->field_flags,
						  info->attribute,
						  info->field_bit_position,
						  info->field_bit_length);
	if (ACPI_FAILURE(status)) {
		acpi_ut_delete_object_desc(obj_desc);
		return_ACPI_STATUS(status);
	}

	/*                                                                    */

	switch (info->field_type) {
	case ACPI_TYPE_LOCAL_REGION_FIELD:

		obj_desc->field.region_obj =
		    acpi_ns_get_attached_object(info->region_node);

		/*                                              */

		obj_desc->field.access_length = info->access_length;

		if (info->connection_node) {
			second_desc = info->connection_node->object;
			if (!(second_desc->common.flags & AOPOBJ_DATA_VALID)) {
				status =
				    acpi_ds_get_buffer_arguments(second_desc);
				if (ACPI_FAILURE(status)) {
					acpi_ut_delete_object_desc(obj_desc);
					return_ACPI_STATUS(status);
				}
			}

			obj_desc->field.resource_buffer =
			    second_desc->buffer.pointer;
			obj_desc->field.resource_length =
			    (u16)second_desc->buffer.length;
		} else if (info->resource_buffer) {
			obj_desc->field.resource_buffer = info->resource_buffer;
			obj_desc->field.resource_length = info->resource_length;
		}

		/*                                            */

		if ((obj_desc->field.region_obj->region.space_id ==
		     ACPI_ADR_SPACE_EC)
		    && (obj_desc->common_field.bit_length > 8)) {
			access_byte_width =
			    ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.
							bit_length);

			/*                                     */

			if (access_byte_width < 256) {
				obj_desc->common_field.access_byte_width =
				    (u8)access_byte_width;
			}
		}
		/*                                           */

		acpi_ut_add_reference(obj_desc->field.region_obj);

		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
				  "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n",
				  obj_desc->field.start_field_bit_offset,
				  obj_desc->field.base_byte_offset,
				  obj_desc->field.access_byte_width,
				  obj_desc->field.region_obj));
		break;

	case ACPI_TYPE_LOCAL_BANK_FIELD:

		obj_desc->bank_field.value = info->bank_value;
		obj_desc->bank_field.region_obj =
		    acpi_ns_get_attached_object(info->region_node);
		obj_desc->bank_field.bank_obj =
		    acpi_ns_get_attached_object(info->register_node);

		/*                                                  */

		acpi_ut_add_reference(obj_desc->bank_field.region_obj);
		acpi_ut_add_reference(obj_desc->bank_field.bank_obj);

		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
				  "Bank Field: BitOff %X, Off %X, Gran %X, Region %p, BankReg %p\n",
				  obj_desc->bank_field.start_field_bit_offset,
				  obj_desc->bank_field.base_byte_offset,
				  obj_desc->field.access_byte_width,
				  obj_desc->bank_field.region_obj,
				  obj_desc->bank_field.bank_obj));

		/*
                                                      
                                                
                                
   */
		second_desc = obj_desc->common.next_object;
		second_desc->extra.aml_start =
		    ACPI_CAST_PTR(union acpi_parse_object,
				  info->data_register_node)->named.data;
		second_desc->extra.aml_length =
		    ACPI_CAST_PTR(union acpi_parse_object,
				  info->data_register_node)->named.length;

		break;

	case ACPI_TYPE_LOCAL_INDEX_FIELD:

		/*                                  */

		obj_desc->index_field.index_obj =
		    acpi_ns_get_attached_object(info->register_node);
		obj_desc->index_field.data_obj =
		    acpi_ns_get_attached_object(info->data_register_node);

		if (!obj_desc->index_field.data_obj
		    || !obj_desc->index_field.index_obj) {
			ACPI_ERROR((AE_INFO,
				    "Null Index Object during field prep"));
			acpi_ut_delete_object_desc(obj_desc);
			return_ACPI_STATUS(AE_AML_INTERNAL);
		}

		/*                                                  */

		acpi_ut_add_reference(obj_desc->index_field.data_obj);
		acpi_ut_add_reference(obj_desc->index_field.index_obj);

		/*
                                             
    
                                                                      
                                                                
    
                                                                     
                                          
    
                                             
                                                      
                                                      
    
                                                 
                                             
                                                    
   */
		obj_desc->index_field.value =
		    (u32) ACPI_ROUND_DOWN(ACPI_DIV_8(info->field_bit_position),
					  obj_desc->index_field.
					  access_byte_width);

		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
				  "IndexField: BitOff %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n",
				  obj_desc->index_field.start_field_bit_offset,
				  obj_desc->index_field.base_byte_offset,
				  obj_desc->index_field.value,
				  obj_desc->field.access_byte_width,
				  obj_desc->index_field.index_obj,
				  obj_desc->index_field.data_obj));
		break;

	default:
		/*                                */
		break;
	}

	/*
                                                                     
                                                  
  */
	status = acpi_ns_attach_object(info->field_node, obj_desc,
				       acpi_ns_get_type(info->field_node));

	ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
			  "Set NamedObj %p [%4.4s], ObjDesc %p\n",
			  info->field_node,
			  acpi_ut_get_node_name(info->field_node), obj_desc));

	/*                                      */

	acpi_ut_remove_reference(obj_desc);
	return_ACPI_STATUS(status);
}
コード例 #11
0
ファイル: dsobject.c プロジェクト: 12rafael/jellytimekernel
static acpi_status
acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
			      union acpi_parse_object *op,
			      union acpi_operand_object **obj_desc_ptr)
{
	union acpi_operand_object *obj_desc;
	acpi_status status;

	ACPI_FUNCTION_TRACE(ds_build_internal_object);

	*obj_desc_ptr = NULL;
	if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
		/*
		 * This is a named object reference. If this name was
		 * previously looked up in the namespace, it was stored in this op.
		 * Otherwise, go ahead and look it up now
		 */
		if (!op->common.node) {
			status = acpi_ns_lookup(walk_state->scope_info,
						op->common.value.string,
						ACPI_TYPE_ANY,
						ACPI_IMODE_EXECUTE,
						ACPI_NS_SEARCH_PARENT |
						ACPI_NS_DONT_OPEN_SCOPE, NULL,
						ACPI_CAST_INDIRECT_PTR(struct
								       acpi_namespace_node,
								       &(op->
									 common.
									 node)));
			if (ACPI_FAILURE(status)) {

				/* Check if we are resolving a named reference within a package */

				if ((status == AE_NOT_FOUND)
				    && (acpi_gbl_enable_interpreter_slack)
				    &&
				    ((op->common.parent->common.aml_opcode ==
				      AML_PACKAGE_OP)
				     || (op->common.parent->common.aml_opcode ==
					 AML_VAR_PACKAGE_OP))) {
					/*
					 * We didn't find the target and we are populating elements
					 * of a package - ignore if slack enabled. Some ASL code
					 * contains dangling invalid references in packages and
					 * expects that no exception will be issued. Leave the
					 * element as a null element. It cannot be used, but it
					 * can be overwritten by subsequent ASL code - this is
					 * typically the case.
					 */
					ACPI_DEBUG_PRINT((ACPI_DB_INFO,
							  "Ignoring unresolved reference in package [%4.4s]\n",
							  walk_state->
							  scope_info->scope.
							  node->name.ascii));

					return_ACPI_STATUS(AE_OK);
				} else {
					ACPI_ERROR_NAMESPACE(op->common.value.
							     string, status);
				}

				return_ACPI_STATUS(status);
			}
		}

		/* Special object resolution for elements of a package */

		if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
		    (op->common.parent->common.aml_opcode ==
		     AML_VAR_PACKAGE_OP)) {
			/*
			 * Attempt to resolve the node to a value before we insert it into
			 * the package. If this is a reference to a common data type,
			 * resolve it immediately. According to the ACPI spec, package
			 * elements can only be "data objects" or method references.
			 * Attempt to resolve to an Integer, Buffer, String or Package.
			 * If cannot, return the named reference (for things like Devices,
			 * Methods, etc.) Buffer Fields and Fields will resolve to simple
			 * objects (int/buf/str/pkg).
			 *
			 * NOTE: References to things like Devices, Methods, Mutexes, etc.
			 * will remain as named references. This behavior is not described
			 * in the ACPI spec, but it appears to be an oversight.
			 */
			obj_desc =
			    ACPI_CAST_PTR(union acpi_operand_object,
					  op->common.node);

			status =
			    acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR
							  (struct
							   acpi_namespace_node,
							   &obj_desc),
							  walk_state);
			if (ACPI_FAILURE(status)) {
				return_ACPI_STATUS(status);
			}

			switch (op->common.node->type) {
				/*
				 * For these types, we need the actual node, not the subobject.
				 * However, the subobject did not get an extra reference count above.
				 *
				 * TBD: should ex_resolve_node_to_value be changed to fix this?
				 */
			case ACPI_TYPE_DEVICE:
			case ACPI_TYPE_THERMAL:

				acpi_ut_add_reference(op->common.node->object);

				/*lint -fallthrough */
				/*
				 * For these types, we need the actual node, not the subobject.
				 * The subobject got an extra reference count in ex_resolve_node_to_value.
				 */
			case ACPI_TYPE_MUTEX:
			case ACPI_TYPE_METHOD:
			case ACPI_TYPE_POWER:
			case ACPI_TYPE_PROCESSOR:
			case ACPI_TYPE_EVENT:
			case ACPI_TYPE_REGION:

				/* We will create a reference object for these types below */
				break;

			default:
				/*
				 * All other types - the node was resolved to an actual
				 * object, we are done.
				 */
				goto exit;
			}
		}
コード例 #12
0
ファイル: utcopy.c プロジェクト: Dronevery/JetsonTK1-kernel
acpi_status
acpi_ut_copy_simple_object (
	union acpi_operand_object       *source_desc,
	union acpi_operand_object       *dest_desc)
{
	u16                             reference_count;
	union acpi_operand_object       *next_object;


	/* Save fields from destination that we don't want to overwrite */

	reference_count = dest_desc->common.reference_count;
	next_object = dest_desc->common.next_object;

	/* Copy the entire source object over the destination object*/

	ACPI_MEMCPY ((char *) dest_desc, (char *) source_desc,
			  sizeof (union acpi_operand_object));

	/* Restore the saved fields */

	dest_desc->common.reference_count = reference_count;
	dest_desc->common.next_object = next_object;

	/* Handle the objects with extra data */

	switch (ACPI_GET_OBJECT_TYPE (dest_desc)) {
	case ACPI_TYPE_BUFFER:

		dest_desc->buffer.node = NULL;
		dest_desc->common.flags = source_desc->common.flags;

		/*
		 * Allocate and copy the actual buffer if and only if:
		 * 1) There is a valid buffer pointer
		 * 2) The buffer is not static (not in an ACPI table) (in this case,
		 *    the actual pointer was already copied above)
		 */
		if ((source_desc->buffer.pointer) &&
			(!(source_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
			dest_desc->buffer.pointer = NULL;

			/* Create an actual buffer only if length > 0 */

			if (source_desc->buffer.length) {
				dest_desc->buffer.pointer =
					ACPI_MEM_ALLOCATE (source_desc->buffer.length);
				if (!dest_desc->buffer.pointer) {
					return (AE_NO_MEMORY);
				}

				/* Copy the actual buffer data */

				ACPI_MEMCPY (dest_desc->buffer.pointer,
						source_desc->buffer.pointer,
						source_desc->buffer.length);
			}
		}
		break;

	case ACPI_TYPE_STRING:

		/*
		 * Allocate and copy the actual string if and only if:
		 * 1) There is a valid string pointer
		 * 2) The string is not static (not in an ACPI table) (in this case,
		 *    the actual pointer was already copied above)
		 */
		if ((source_desc->string.pointer) &&
			(!(source_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
			dest_desc->string.pointer =
				ACPI_MEM_ALLOCATE ((acpi_size) source_desc->string.length + 1);
			if (!dest_desc->string.pointer) {
				return (AE_NO_MEMORY);
			}

			ACPI_MEMCPY (dest_desc->string.pointer, source_desc->string.pointer,
					  (acpi_size) source_desc->string.length + 1);
		}
		break;

	case ACPI_TYPE_LOCAL_REFERENCE:
		/*
		 * We copied the reference object, so we now must add a reference
		 * to the object pointed to by the reference
		 */
		acpi_ut_add_reference (source_desc->reference.object);
		break;

	default:
		/* Nothing to do for other simple objects */
		break;
	}

	return (AE_OK);
}
コード例 #13
0
ファイル: dsmthdat.c プロジェクト: jhbsz/MI424WR_GEN2_Rev_E-F
acpi_status
acpi_ds_method_data_get_value (
    u16                     opcode,
    u32                     index,
    acpi_walk_state         *walk_state,
    acpi_operand_object     **dest_desc)
{
    acpi_status             status;
    acpi_operand_object     **entry;
    acpi_operand_object     *object;


    FUNCTION_TRACE ("Ds_method_data_get_value");


    /* Validate the object descriptor */

    if (!dest_desc) {
        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null object descriptor pointer\n"));
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }


    /* Get a pointer to the requested method stack entry */

    status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry);
    if (ACPI_FAILURE (status)) {
        return_ACPI_STATUS (status);
    }

    /* Get the object from the method stack */

    object = *entry;


    /* Examine the returned object, it must be valid. */

    if (!object) {
        /*
         * Index points to uninitialized object stack value.
         * This means that either 1) The expected argument was
         * not passed to the method, or 2) A local variable
         * was referenced by the method (via the ASL)
         * before it was initialized.  Either case is an error.
         */
        switch (opcode) {
        case AML_ARG_OP:

            ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Uninitialized Arg[%d] at entry %p\n",
                               index, entry));

            return_ACPI_STATUS (AE_AML_UNINITIALIZED_ARG);
            break;

        case AML_LOCAL_OP:

            ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Uninitialized Local[%d] at entry %p\n",
                               index, entry));

            return_ACPI_STATUS (AE_AML_UNINITIALIZED_LOCAL);
            break;
        }
    }


    /*
     * Index points to initialized and valid object stack value.
     * Return an additional reference to the object
     */
    *dest_desc = object;
    acpi_ut_add_reference (object);

    return_ACPI_STATUS (AE_OK);
}
コード例 #14
0
acpi_status
acpi_install_notify_handler(acpi_handle device,
			    u32 handler_type,
			    acpi_notify_handler handler, void *context)
{
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *notify_obj;
	struct acpi_namespace_node *node;
	acpi_status status;

	ACPI_FUNCTION_TRACE(acpi_install_notify_handler);

	

	if ((!device) ||
	    (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	

	node = acpi_ns_map_handle_to_node(device);
	if (!node) {
		status = AE_BAD_PARAMETER;
		goto unlock_and_exit;
	}

	
	if (device == ACPI_ROOT_OBJECT) {

		

		if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
		     acpi_gbl_system_notify.handler) ||
		    ((handler_type & ACPI_DEVICE_NOTIFY) &&
		     acpi_gbl_device_notify.handler)) {
			status = AE_ALREADY_EXISTS;
			goto unlock_and_exit;
		}

		if (handler_type & ACPI_SYSTEM_NOTIFY) {
			acpi_gbl_system_notify.node = node;
			acpi_gbl_system_notify.handler = handler;
			acpi_gbl_system_notify.context = context;
		}

		if (handler_type & ACPI_DEVICE_NOTIFY) {
			acpi_gbl_device_notify.node = node;
			acpi_gbl_device_notify.handler = handler;
			acpi_gbl_device_notify.context = context;
		}

		
	}

	
	else {
		

		if (!acpi_ev_is_notify_object(node)) {
			status = AE_TYPE;
			goto unlock_and_exit;
		}

		

		obj_desc = acpi_ns_get_attached_object(node);
		if (obj_desc) {

			

			if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
			     obj_desc->common_notify.system_notify) ||
			    ((handler_type & ACPI_DEVICE_NOTIFY) &&
			     obj_desc->common_notify.device_notify)) {
				status = AE_ALREADY_EXISTS;
				goto unlock_and_exit;
			}
		} else {
			

			obj_desc = acpi_ut_create_internal_object(node->type);
			if (!obj_desc) {
				status = AE_NO_MEMORY;
				goto unlock_and_exit;
			}

			

			status =
			    acpi_ns_attach_object(device, obj_desc, node->type);

			

			acpi_ut_remove_reference(obj_desc);
			if (ACPI_FAILURE(status)) {
				goto unlock_and_exit;
			}
		}

		

		notify_obj =
		    acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY);
		if (!notify_obj) {
			status = AE_NO_MEMORY;
			goto unlock_and_exit;
		}

		notify_obj->notify.node = node;
		notify_obj->notify.handler = handler;
		notify_obj->notify.context = context;

		if (handler_type & ACPI_SYSTEM_NOTIFY) {
			obj_desc->common_notify.system_notify = notify_obj;
		}

		if (handler_type & ACPI_DEVICE_NOTIFY) {
			obj_desc->common_notify.device_notify = notify_obj;
		}

		if (handler_type == ACPI_ALL_NOTIFY) {

			

			acpi_ut_add_reference(notify_obj);
		}
	}

      unlock_and_exit:
	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
	return_ACPI_STATUS(status);
}
コード例 #15
0
ファイル: psxface.c プロジェクト: kzlin129/tt-gpl
acpi_status
acpi_psx_execute (
	struct acpi_parameter_info      *info)
{
	acpi_status                     status;
	union acpi_operand_object       *obj_desc;
	u32                             i;
	union acpi_parse_object         *op;
	struct acpi_walk_state          *walk_state;


	ACPI_FUNCTION_TRACE ("psx_execute");


	/* Validate the Node and get the attached object */

	if (!info || !info->node) {
		return_ACPI_STATUS (AE_NULL_ENTRY);
	}

	obj_desc = acpi_ns_get_attached_object (info->node);
	if (!obj_desc) {
		return_ACPI_STATUS (AE_NULL_OBJECT);
	}

	/* Init for new method, wait on concurrency semaphore */

	status = acpi_ds_begin_method_execution (info->node, obj_desc, NULL);
	if (ACPI_FAILURE (status)) {
		return_ACPI_STATUS (status);
	}

	if ((info->parameter_type == ACPI_PARAM_ARGS) &&
		(info->parameters)) {
		/*
		 * The caller "owns" the parameters, so give each one an extra
		 * reference
		 */
		for (i = 0; info->parameters[i]; i++) {
			acpi_ut_add_reference (info->parameters[i]);
		}
	}

	/*
	 * 1) Perform the first pass parse of the method to enter any
	 * named objects that it creates into the namespace
	 */
	ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
		"**** Begin Method Parse **** Entry=%p obj=%p\n",
		info->node, obj_desc));

	/* Create and init a Root Node */

	op = acpi_ps_create_scope_op ();
	if (!op) {
		status = AE_NO_MEMORY;
		goto cleanup1;
	}

	/*
	 * Get a new owner_id for objects created by this method. Namespace
	 * objects (such as Operation Regions) can be created during the
	 * first pass parse.
	 */
	obj_desc->method.owning_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD);

	/* Create and initialize a new walk state */

	walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id,
			   NULL, NULL, NULL);
	if (!walk_state) {
		status = AE_NO_MEMORY;
		goto cleanup2;
	}

	status = acpi_ds_init_aml_walk (walk_state, op, info->node,
			  obj_desc->method.aml_start,
			  obj_desc->method.aml_length, NULL, 1);
	if (ACPI_FAILURE (status)) {
		goto cleanup3;
	}

	/* Parse the AML */

	status = acpi_ps_parse_aml (walk_state);
	acpi_ps_delete_parse_tree (op);
	if (ACPI_FAILURE (status)) {
		goto cleanup1; /* Walk state is already deleted */
	}

	/*
	 * 2) Execute the method.  Performs second pass parse simultaneously
	 */
	ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
		"**** Begin Method Execution **** Entry=%p obj=%p\n",
		info->node, obj_desc));

	/* Create and init a Root Node */

	op = acpi_ps_create_scope_op ();
	if (!op) {
		status = AE_NO_MEMORY;
		goto cleanup1;
	}

	/* Init new op with the method name and pointer back to the NS node */

	acpi_ps_set_name (op, info->node->name.integer);
	op->common.node = info->node;

	/* Create and initialize a new walk state */

	walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL);
	if (!walk_state) {
		status = AE_NO_MEMORY;
		goto cleanup2;
	}

	status = acpi_ds_init_aml_walk (walk_state, op, info->node,
			  obj_desc->method.aml_start,
			  obj_desc->method.aml_length, info, 3);
	if (ACPI_FAILURE (status)) {
		goto cleanup3;
	}

	/* The walk of the parse tree is where we actually execute the method */

	status = acpi_ps_parse_aml (walk_state);
	goto cleanup2; /* Walk state already deleted */


cleanup3:
	acpi_ds_delete_walk_state (walk_state);

cleanup2:
	acpi_ps_delete_parse_tree (op);

cleanup1:
	if ((info->parameter_type == ACPI_PARAM_ARGS) &&
		(info->parameters)) {
		/* Take away the extra reference that we gave the parameters above */

		for (i = 0; info->parameters[i]; i++) {
			/* Ignore errors, just do them all */

			(void) acpi_ut_update_object_reference (
					 info->parameters[i], REF_DECREMENT);
		}
	}

	if (ACPI_FAILURE (status)) {
		return_ACPI_STATUS (status);
	}

	/*
	 * If the method has returned an object, signal this to the caller with
	 * a control exception code
	 */
	if (info->return_object) {
		ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Method returned obj_desc=%p\n",
			info->return_object));
		ACPI_DUMP_STACK_ENTRY (info->return_object);

		status = AE_CTRL_RETURN_VALUE;
	}

	return_ACPI_STATUS (status);
}
コード例 #16
0
ファイル: dsmthdat.c プロジェクト: 3sOx/asuswrt-merlin
acpi_status
acpi_ds_method_data_get_value(u16 opcode,
			      u32 index,
			      struct acpi_walk_state *walk_state,
			      union acpi_operand_object **dest_desc)
{
	acpi_status status;
	struct acpi_namespace_node *node;
	union acpi_operand_object *object;

	ACPI_FUNCTION_TRACE(ds_method_data_get_value);

	/* Validate the object descriptor */

	if (!dest_desc) {
		ACPI_ERROR((AE_INFO, "Null object descriptor pointer"));
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	/* Get the namespace node for the arg/local */

	status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Get the object from the node */

	object = node->object;

	/* Examine the returned object, it must be valid. */

	if (!object) {
		/*
		 * Index points to uninitialized object.
		 * This means that either 1) The expected argument was
		 * not passed to the method, or 2) A local variable
		 * was referenced by the method (via the ASL)
		 * before it was initialized.  Either case is an error.
		 */

		/* If slack enabled, init the local_x/arg_x to an Integer of value zero */

		if (acpi_gbl_enable_interpreter_slack) {
			object =
			    acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
			if (!object) {
				return_ACPI_STATUS(AE_NO_MEMORY);
			}

			object->integer.value = 0;
			node->object = object;
		}

		/* Otherwise, return the error */

		else
			switch (opcode) {
			case AML_ARG_OP:

				ACPI_ERROR((AE_INFO,
					    "Uninitialized Arg[%d] at node %p",
					    index, node));

				return_ACPI_STATUS(AE_AML_UNINITIALIZED_ARG);

			case AML_LOCAL_OP:

				ACPI_ERROR((AE_INFO,
					    "Uninitialized Local[%d] at node %p",
					    index, node));

				return_ACPI_STATUS(AE_AML_UNINITIALIZED_LOCAL);

			default:
				ACPI_ERROR((AE_INFO,
					    "Not a Arg/Local opcode: %X",
					    opcode));
				return_ACPI_STATUS(AE_AML_INTERNAL);
			}
	}

	/*
	 * The Index points to an initialized and valid object.
	 * Return an additional reference to the object
	 */
	*dest_desc = object;
	acpi_ut_add_reference(object);

	return_ACPI_STATUS(AE_OK);
}
コード例 #17
0
ファイル: exoparg1.c プロジェクト: FatSunHYS/OSCourseDesign
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;
	}
コード例 #18
0
ファイル: exoparg1.c プロジェクト: FatSunHYS/OSCourseDesign
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);
}
コード例 #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);
}
コード例 #20
0
ファイル: exstore.c プロジェクト: GodFox/magx_kernel_xpixl
acpi_status
acpi_ex_store_object_to_index (
	union acpi_operand_object       *source_desc,
	union acpi_operand_object       *index_desc,
	struct acpi_walk_state          *walk_state)
{
	acpi_status                     status = AE_OK;
	union acpi_operand_object       *obj_desc;
	union acpi_operand_object       *new_desc;
	u8                              value = 0;
	u32                             i;


	ACPI_FUNCTION_TRACE ("ex_store_object_to_index");


	/*
	 * Destination must be a reference pointer, and
	 * must point to either a buffer or a package
	 */
	switch (index_desc->reference.target_type) {
	case ACPI_TYPE_PACKAGE:
		/*
		 * Storing to a package element is not simple.  The source must be
		 * evaluated and converted to the type of the destination and then the
		 * source is copied into the destination - we can't just point to the
		 * source object.
		 */
		/*
		 * The object at *(index_desc->Reference.Where) is the
		 * element within the package that is to be modified.
		 * The parent package object is at index_desc->Reference.Object
		 */
		obj_desc = *(index_desc->reference.where);

		/* Do the conversion/store */

		status = acpi_ex_store_object_to_object (source_desc, obj_desc, &new_desc,
				  walk_state);
		if (ACPI_FAILURE (status)) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
				"Could not store object to indexed package element\n"));
			return_ACPI_STATUS (status);
		}

		/*
		 * If a new object was created, we must install it as the new
		 * package element
		 */
		if (new_desc != obj_desc) {
			acpi_ut_remove_reference (obj_desc);
			*(index_desc->reference.where) = new_desc;

			/* If same as the original source, add a reference */

			if (new_desc == source_desc) {
				acpi_ut_add_reference (new_desc);
			}

			/* Increment reference count by the ref count of the parent package -1 */

			for (i = 1; i < ((union acpi_operand_object *) index_desc->reference.object)->common.reference_count; i++) {
				acpi_ut_add_reference (new_desc);
			}
		}
		break;


	case ACPI_TYPE_BUFFER_FIELD:

		/*
		 * Store into a Buffer (not actually a real buffer_field) at a
		 * location defined by an Index.
		 *
		 * The first 8-bit element of the source object is written to the
		 * 8-bit Buffer location defined by the Index destination object,
		 * according to the ACPI 2.0 specification.
		 */

		/*
		 * Make sure the target is a Buffer
		 */
		obj_desc = index_desc->reference.object;
		if (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_BUFFER) {
			return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
		}

		/*
		 * The assignment of the individual elements will be slightly
		 * different for each source type.
		 */
		switch (ACPI_GET_OBJECT_TYPE (source_desc)) {
		case ACPI_TYPE_INTEGER:

			/* Use the least-significant byte of the integer */

			value = (u8) (source_desc->integer.value);
			break;

		case ACPI_TYPE_BUFFER:

			value = source_desc->buffer.pointer[0];
			break;

		case ACPI_TYPE_STRING:

			value = (u8) source_desc->string.pointer[0];
			break;

		default:

			/* All other types are invalid */

			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
				"Source must be Integer/Buffer/String type, not %s\n",
				acpi_ut_get_object_type_name (source_desc)));
			return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
		}

		/* Store the source value into the target buffer byte */

		obj_desc->buffer.pointer[index_desc->reference.offset] = value;
		break;


	default:
		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
			"Target is not a Package or buffer_field\n"));
		status = AE_AML_OPERAND_TYPE;
		break;
	}

	return_ACPI_STATUS (status);
}
コード例 #21
0
ファイル: evxface.c プロジェクト: 0x000000FF/edison-linux
acpi_status
acpi_install_notify_handler(acpi_handle device,
			    u32 handler_type,
			    acpi_notify_handler handler, void *context)
{
	struct acpi_namespace_node *node =
	    ACPI_CAST_PTR(struct acpi_namespace_node, device);
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *handler_obj;
	acpi_status status;
	u32 i;

	ACPI_FUNCTION_TRACE(acpi_install_notify_handler);

	/* Parameter validation */

	if ((!device) || (!handler) || (!handler_type) ||
	    (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/*
	 * Root Object:
	 * Registering a notify handler on the root object indicates that the
	 * caller wishes to receive notifications for all objects. Note that
	 * only one global handler can be registered per notify type.
	 * Ensure that a handler is not already installed.
	 */
	if (device == ACPI_ROOT_OBJECT) {
		for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
			if (handler_type & (i + 1)) {
				if (acpi_gbl_global_notify[i].handler) {
					status = AE_ALREADY_EXISTS;
					goto unlock_and_exit;
				}

				acpi_gbl_global_notify[i].handler = handler;
				acpi_gbl_global_notify[i].context = context;
			}
		}

		goto unlock_and_exit;	/* Global notify handler installed, all done */
	}

	/*
	 * All Other Objects:
	 * Caller will only receive notifications specific to the target
	 * object. Note that only certain object types are allowed to
	 * receive notifications.
	 */

	/* Are Notifies allowed on this object? */

	if (!acpi_ev_is_notify_object(node)) {
		status = AE_TYPE;
		goto unlock_and_exit;
	}

	/* Check for an existing internal object, might not exist */

	obj_desc = acpi_ns_get_attached_object(node);
	if (!obj_desc) {

		/* Create a new object */

		obj_desc = acpi_ut_create_internal_object(node->type);
		if (!obj_desc) {
			status = AE_NO_MEMORY;
			goto unlock_and_exit;
		}

		/* Attach new object to the Node, remove local reference */

		status = acpi_ns_attach_object(device, obj_desc, node->type);
		acpi_ut_remove_reference(obj_desc);
		if (ACPI_FAILURE(status)) {
			goto unlock_and_exit;
		}
	}

	/* Ensure that the handler is not already installed in the lists */

	for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
		if (handler_type & (i + 1)) {
			handler_obj = obj_desc->common_notify.notify_list[i];
			while (handler_obj) {
				if (handler_obj->notify.handler == handler) {
					status = AE_ALREADY_EXISTS;
					goto unlock_and_exit;
				}

				handler_obj = handler_obj->notify.next[i];
			}
		}
	}

	/* Create and populate a new notify handler object */

	handler_obj = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY);
	if (!handler_obj) {
		status = AE_NO_MEMORY;
		goto unlock_and_exit;
	}

	handler_obj->notify.node = node;
	handler_obj->notify.handler_type = handler_type;
	handler_obj->notify.handler = handler;
	handler_obj->notify.context = context;

	/* Install the handler at the list head(s) */

	for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
		if (handler_type & (i + 1)) {
			handler_obj->notify.next[i] =
			    obj_desc->common_notify.notify_list[i];

			obj_desc->common_notify.notify_list[i] = handler_obj;
		}
	}

	/* Add an extra reference if handler was installed in both lists */

	if (handler_type == ACPI_ALL_NOTIFY) {
		acpi_ut_add_reference(handler_obj);
	}

unlock_and_exit:
	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
	return_ACPI_STATUS(status);
}
コード例 #22
0
ファイル: nsobject.c プロジェクト: 1314cc/linux
/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_attach_object
 *
 * PARAMETERS:  node                - Parent Node
 *              object              - Object to be attached
 *              type                - Type of object, or ACPI_TYPE_ANY if not
 *                                    known
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Record the given object as the value associated with the
 *              name whose acpi_handle is passed. If Object is NULL
 *              and Type is ACPI_TYPE_ANY, set the name as having no value.
 *              Note: Future may require that the Node->Flags field be passed
 *              as a parameter.
 *
 * MUTEX:       Assumes namespace is locked
 *
 ******************************************************************************/
acpi_status
acpi_ns_attach_object(struct acpi_namespace_node *node,
		      union acpi_operand_object *object, acpi_object_type type)
{
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *last_obj_desc;
	acpi_object_type object_type = ACPI_TYPE_ANY;

	ACPI_FUNCTION_TRACE(ns_attach_object);

	/*
	 * Parameter validation
	 */
	if (!node) {

		/* Invalid handle */

		ACPI_ERROR((AE_INFO, "Null NamedObj handle"));
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	if (!object && (ACPI_TYPE_ANY != type)) {

		/* Null object */

		ACPI_ERROR((AE_INFO,
			    "Null object, but type not ACPI_TYPE_ANY"));
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {

		/* Not a name handle */

		ACPI_ERROR((AE_INFO, "Invalid handle %p [%s]",
			    node, acpi_ut_get_descriptor_name(node)));
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	/* Check if this object is already attached */

	if (node->object == object) {
		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
				  "Obj %p already installed in NameObj %p\n",
				  object, node));

		return_ACPI_STATUS(AE_OK);
	}

	/* If null object, we will just install it */

	if (!object) {
		obj_desc = NULL;
		object_type = ACPI_TYPE_ANY;
	}

	/*
	 * If the source object is a namespace Node with an attached object,
	 * we will use that (attached) object
	 */
	else if ((ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) &&
		 ((struct acpi_namespace_node *)object)->object) {
		/*
		 * Value passed is a name handle and that name has a
		 * non-null value. Use that name's value and type.
		 */
		obj_desc = ((struct acpi_namespace_node *)object)->object;
		object_type = ((struct acpi_namespace_node *)object)->type;
	}

	/*
	 * Otherwise, we will use the parameter object, but we must type
	 * it first
	 */
	else {
		obj_desc = (union acpi_operand_object *)object;

		/* Use the given type */

		object_type = type;
	}

	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n",
			  obj_desc, node, acpi_ut_get_node_name(node)));

	/* Detach an existing attached object if present */

	if (node->object) {
		acpi_ns_detach_object(node);
	}

	if (obj_desc) {
		/*
		 * Must increment the new value's reference count
		 * (if it is an internal object)
		 */
		acpi_ut_add_reference(obj_desc);

		/*
		 * Handle objects with multiple descriptors - walk
		 * to the end of the descriptor list
		 */
		last_obj_desc = obj_desc;
		while (last_obj_desc->common.next_object) {
			last_obj_desc = last_obj_desc->common.next_object;
		}

		/* Install the object at the front of the object list */

		last_obj_desc->common.next_object = node->object;
	}

	node->type = (u8) object_type;
	node->object = obj_desc;

	return_ACPI_STATUS(AE_OK);
}
コード例 #23
0
acpi_status
acpi_ex_resolve_node_to_value (
	acpi_namespace_node     **object_ptr,
	acpi_walk_state         *walk_state)

{
	acpi_status             status = AE_OK;
	acpi_operand_object     *source_desc;
	acpi_operand_object     *obj_desc = NULL;
	acpi_namespace_node     *node;
	acpi_object_type8       entry_type;
	acpi_integer            temp_val;


	FUNCTION_TRACE ("Ex_resolve_node_to_value");


	/*
	 * The stack pointer points to a 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 Type=%X\n",
		 node, source_desc, entry_type));


	/*
	 * 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_TYPE_PACKAGE != source_desc->common.type) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a Package, type %s\n",
				acpi_ut_get_type_name (source_desc->common.type)));
			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:

		if (ACPI_TYPE_BUFFER != source_desc->common.type) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a Buffer, type %s\n",
				acpi_ut_get_type_name (source_desc->common.type)));
			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_STRING:

		if (ACPI_TYPE_STRING != source_desc->common.type) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a String, type %s\n",
				acpi_ut_get_type_name (source_desc->common.type)));
			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_TYPE_INTEGER != source_desc->common.type) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a Integer, type %s\n",
				acpi_ut_get_type_name (source_desc->common.type)));
			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 INTERNAL_TYPE_REGION_FIELD:
	case INTERNAL_TYPE_BANK_FIELD:
	case INTERNAL_TYPE_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 (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 */
		break;


	/*
	 * The only named references allowed are named constants
	 *   e.g. -- Name (\OSFL, Ones)
	 */
	case INTERNAL_TYPE_REFERENCE:

		switch (source_desc->reference.opcode) {

		case AML_ZERO_OP:

			temp_val = 0;
			break;

		case AML_ONE_OP:

			temp_val = 1;
			break;

		case AML_ONES_OP:

			temp_val = ACPI_INTEGER_MAX;
			break;

		case AML_REVISION_OP:

			temp_val = ACPI_CA_SUPPORT_LEVEL;
			break;

		default:

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

			return_ACPI_STATUS (AE_AML_BAD_OPCODE);
		}

		/* Create object for result */

		obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
		if (!obj_desc) {
			return_ACPI_STATUS (AE_NO_MEMORY);
		}

		obj_desc->integer.value = temp_val;

		/*
		 * Truncate value if we are executing from a 32-bit ACPI table
		 * AND actually executing AML code.  If we are resolving
		 * an object in the namespace via an external call to the
		 * subsystem, we will have a null Walk_state
		 */
		if (walk_state) {
			acpi_ex_truncate_for32bit_table (obj_desc, walk_state);
		}
		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);
}
コード例 #24
0
acpi_status
acpi_ns_attach_object(struct acpi_namespace_node *node,
		      union acpi_operand_object *object, acpi_object_type type)
{
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *last_obj_desc;
	acpi_object_type object_type = ACPI_TYPE_ANY;

	ACPI_FUNCTION_TRACE(ns_attach_object);

	if (!node) {

		

		ACPI_ERROR((AE_INFO, "Null NamedObj handle"));
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	if (!object && (ACPI_TYPE_ANY != type)) {

		

		ACPI_ERROR((AE_INFO,
			    "Null object, but type not ACPI_TYPE_ANY"));
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {

		

		ACPI_ERROR((AE_INFO, "Invalid handle %p [%s]",
			    node, acpi_ut_get_descriptor_name(node)));
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	

	if (node->object == object) {
		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
				  "Obj %p already installed in NameObj %p\n",
				  object, node));

		return_ACPI_STATUS(AE_OK);
	}

	

	if (!object) {
		obj_desc = NULL;
		object_type = ACPI_TYPE_ANY;
	}

	else if ((ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) &&
		 ((struct acpi_namespace_node *)object)->object) {
		obj_desc = ((struct acpi_namespace_node *)object)->object;
		object_type = ((struct acpi_namespace_node *)object)->type;
	}

	else {
		obj_desc = (union acpi_operand_object *)object;

		

		object_type = type;
	}

	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n",
			  obj_desc, node, acpi_ut_get_node_name(node)));

	

	if (node->object) {
		acpi_ns_detach_object(node);
	}

	if (obj_desc) {
		acpi_ut_add_reference(obj_desc);

		last_obj_desc = obj_desc;
		while (last_obj_desc->common.next_object) {
			last_obj_desc = last_obj_desc->common.next_object;
		}

		

		last_obj_desc->common.next_object = node->object;
	}

	node->type = (u8) object_type;
	node->object = obj_desc;

	return_ACPI_STATUS(AE_OK);
}
コード例 #25
0
acpi_status
acpi_psx_execute (
	acpi_namespace_node     *method_node,
	acpi_operand_object     **params,
	acpi_operand_object     **return_obj_desc)
{
	acpi_status             status;
	acpi_operand_object     *obj_desc;
	u32                     i;
	acpi_parse_object       *op;
	acpi_walk_state         *walk_state;


	FUNCTION_TRACE ("Psx_execute");


	/* Validate the Node and get the attached object */

	if (!method_node) {
		return_ACPI_STATUS (AE_NULL_ENTRY);
	}

	obj_desc = acpi_ns_get_attached_object (method_node);
	if (!obj_desc) {
		return_ACPI_STATUS (AE_NULL_OBJECT);
	}

	/* Init for new method, wait on concurrency semaphore */

	status = acpi_ds_begin_method_execution (method_node, obj_desc, NULL);
	if (ACPI_FAILURE (status)) {
		return_ACPI_STATUS (status);
	}

	if (params) {
		/*
		 * The caller "owns" the parameters, so give each one an extra
		 * reference
		 */
		for (i = 0; params[i]; i++) {
			acpi_ut_add_reference (params[i]);
		}
	}

	/*
	 * 1) Perform the first pass parse of the method to enter any
	 * named objects that it creates into the namespace
	 */
	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
		"**** Begin Method Parse **** Entry=%p obj=%p\n",
		method_node, obj_desc));

	/* Create and init a Root Node */

	op = acpi_ps_alloc_op (AML_SCOPE_OP);
	if (!op) {
		return_ACPI_STATUS (AE_NO_MEMORY);
	}

	/* Create and initialize a new walk state */

	walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT,
			   NULL, NULL, NULL);
	if (!walk_state) {
		return_ACPI_STATUS (AE_NO_MEMORY);
	}

	status = acpi_ds_init_aml_walk (walk_state, op, method_node, obj_desc->method.aml_start,
			  obj_desc->method.aml_length, NULL, NULL, 1);
	if (ACPI_FAILURE (status)) {
		/* TBD: delete walk state */
		return_ACPI_STATUS (status);
	}

	/* Parse the AML */

	status = acpi_ps_parse_aml (walk_state);
	acpi_ps_delete_parse_tree (op);


	/*
	 * 2) Execute the method.  Performs second pass parse simultaneously
	 */
	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
		"**** Begin Method Execution **** Entry=%p obj=%p\n",
		method_node, obj_desc));

	/* Create and init a Root Node */

	op = acpi_ps_alloc_op (AML_SCOPE_OP);
	if (!op) {
		return_ACPI_STATUS (AE_NO_MEMORY);
	}

	/* Init new op with the method name and pointer back to the NS node */

	acpi_ps_set_name (op, method_node->name);
	op->node = method_node;

	/* Create and initialize a new walk state */

	walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT,
			   NULL, NULL, NULL);
	if (!walk_state) {
		return_ACPI_STATUS (AE_NO_MEMORY);
	}

	status = acpi_ds_init_aml_walk (walk_state, op, method_node, obj_desc->method.aml_start,
			  obj_desc->method.aml_length, params, return_obj_desc, 3);
	if (ACPI_FAILURE (status)) {
		/* TBD: delete walk state */
		return_ACPI_STATUS (status);
	}

	/*
	 * The walk of the parse tree is where we actually execute the method
	 */
	status = acpi_ps_parse_aml (walk_state);
	acpi_ps_delete_parse_tree (op);

	if (params) {
		/* Take away the extra reference that we gave the parameters above */

		for (i = 0; params[i]; i++) {
			acpi_ut_update_object_reference (params[i], REF_DECREMENT);
		}
	}


	if (ACPI_FAILURE (status)) {
		DUMP_PATHNAME (method_node, "Ps_execute: method failed -",
			ACPI_LV_ERROR, _COMPONENT);
	}


	/*
	 * If the method has returned an object, signal this to the caller with
	 * a control exception code
	 */
	if (*return_obj_desc) {
		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Method returned Obj_desc=%p\n",
			*return_obj_desc));
		DUMP_STACK_ENTRY (*return_obj_desc);

		status = AE_CTRL_RETURN_VALUE;
	}


	return_ACPI_STATUS (status);
}