예제 #1
0
acpi_status
acpi_evaluate_object (
	acpi_handle                     handle,
	acpi_string                     pathname,
	struct acpi_object_list         *external_params,
	struct acpi_buffer              *return_buffer)
{
	acpi_status                     status;
	acpi_status                     status2;
	struct acpi_parameter_info      info;
	acpi_size                       buffer_space_needed;
	u32                             i;


	ACPI_FUNCTION_TRACE ("acpi_evaluate_object");


	info.node = handle;
	info.parameters = NULL;
	info.return_object = NULL;
	info.parameter_type = ACPI_PARAM_ARGS;

	/*
	 * If there are parameters to be passed to the object
	 * (which must be a control method), the external objects
	 * must be converted to internal objects
	 */
	if (external_params && external_params->count) {
		/*
		 * Allocate a new parameter block for the internal objects
		 * Add 1 to count to allow for null terminated internal list
		 */
		info.parameters = ACPI_MEM_CALLOCATE (
				 ((acpi_size) external_params->count + 1) *
				 sizeof (void *));
		if (!info.parameters) {
			return_ACPI_STATUS (AE_NO_MEMORY);
		}

		/*
		 * Convert each external object in the list to an
		 * internal object
		 */
		for (i = 0; i < external_params->count; i++) {
			status = acpi_ut_copy_eobject_to_iobject (&external_params->pointer[i],
					  &info.parameters[i]);
			if (ACPI_FAILURE (status)) {
				acpi_ut_delete_internal_object_list (info.parameters);
				return_ACPI_STATUS (status);
			}
		}
		info.parameters[external_params->count] = NULL;
	}


	/*
	 * Three major cases:
	 * 1) Fully qualified pathname
	 * 2) No handle, not fully qualified pathname (error)
	 * 3) Valid handle
	 */
	if ((pathname) &&
		(acpi_ns_valid_root_prefix (pathname[0]))) {
		/*
		 *  The path is fully qualified, just evaluate by name
		 */
		status = acpi_ns_evaluate_by_name (pathname, &info);
	}
	else if (!handle) {
		/*
		 * A handle is optional iff a fully qualified pathname
		 * is specified.  Since we've already handled fully
		 * qualified names above, this is an error
		 */
		if (!pathname) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
				"Both Handle and Pathname are NULL\n"));
		}
		else {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
				"Handle is NULL and Pathname is relative\n"));
		}

		status = AE_BAD_PARAMETER;
	}
	else {
		/*
		 * We get here if we have a handle -- and if we have a
		 * pathname it is relative.  The handle will be validated
		 * in the lower procedures
		 */
		if (!pathname) {
			/*
			 * The null pathname case means the handle is for
			 * the actual object to be evaluated
			 */
			status = acpi_ns_evaluate_by_handle (&info);
		}
		else {
		   /*
			* Both a Handle and a relative Pathname
			*/
			status = acpi_ns_evaluate_relative (pathname, &info);
		}
	}


	/*
	 * If we are expecting a return value, and all went well above,
	 * copy the return value to an external object.
	 */
	if (return_buffer) {
		if (!info.return_object) {
			return_buffer->length = 0;
		}
		else {
			if (ACPI_GET_DESCRIPTOR_TYPE (info.return_object) == ACPI_DESC_TYPE_NAMED) {
				/*
				 * If we received a NS Node as a return object, this means that
				 * the object we are evaluating has nothing interesting to
				 * return (such as a mutex, etc.)  We return an error because
				 * these types are essentially unsupported by this interface.
				 * We don't check up front because this makes it easier to add
				 * support for various types at a later date if necessary.
				 */
				status = AE_TYPE;
				info.return_object = NULL;  /* No need to delete a NS Node */
				return_buffer->length = 0;
			}

			if (ACPI_SUCCESS (status)) {
				/*
				 * Find out how large a buffer is needed
				 * to contain the returned object
				 */
				status = acpi_ut_get_object_size (info.return_object,
						   &buffer_space_needed);
				if (ACPI_SUCCESS (status)) {
					/* Validate/Allocate/Clear caller buffer */

					status = acpi_ut_initialize_buffer (return_buffer, buffer_space_needed);
					if (ACPI_FAILURE (status)) {
						/*
						 * Caller's buffer is too small or a new one can't be allocated
						 */
						ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
							"Needed buffer size %X, %s\n",
							(u32) buffer_space_needed,
							acpi_format_exception (status)));
					}
					else {
						/*
						 *  We have enough space for the object, build it
						 */
						status = acpi_ut_copy_iobject_to_eobject (info.return_object,
								  return_buffer);
					}
				}
			}
		}
	}

	if (info.return_object) {
		/*
		 * Delete the internal return object.  NOTE: Interpreter
		 * must be locked to avoid race condition.
		 */
		status2 = acpi_ex_enter_interpreter ();
		if (ACPI_SUCCESS (status2)) {
			/*
			 * Delete the internal return object. (Or at least
			 * decrement the reference count by one)
			 */
			acpi_ut_remove_reference (info.return_object);
			acpi_ex_exit_interpreter ();
		}
	}

	/*
	 * Free the input parameter list (if we created one),
	 */
	if (info.parameters) {
		/* Free the allocated parameter block */

		acpi_ut_delete_internal_object_list (info.parameters);
	}

	return_ACPI_STATUS (status);
}
예제 #2
0
파일: nsxfobj.c 프로젝트: davidbau/davej
ACPI_STATUS
acpi_evaluate_object (
	ACPI_HANDLE             handle,
	ACPI_STRING             pathname,
	ACPI_OBJECT_LIST        *param_objects,
	ACPI_BUFFER             *return_buffer)
{
	ACPI_STATUS             status;
	ACPI_OPERAND_OBJECT     **param_ptr = NULL;
	ACPI_OPERAND_OBJECT     *return_obj = NULL;
	ACPI_OPERAND_OBJECT     *object_ptr = NULL;
	u32                     buffer_space_needed;
	u32                     user_buffer_length;
	u32                     count;
	u32                     i;
	u32                     param_length;
	u32                     object_length;


	/*
	 * If there are parameters to be passed to the object
	 * (which must be a control method), the external objects
	 * must be converted to internal objects
	 */

	if (param_objects && param_objects->count) {
		/*
		 * Allocate a new parameter block for the internal objects
		 * Add 1 to count to allow for null terminated internal list
		 */

		count           = param_objects->count;
		param_length    = (count + 1) * sizeof (void *);
		object_length   = count * sizeof (ACPI_OPERAND_OBJECT);

		param_ptr = acpi_cm_callocate (param_length + /* Parameter List part */
				  object_length); /* Actual objects */
		if (!param_ptr) {
			return (AE_NO_MEMORY);
		}

		object_ptr = (ACPI_OPERAND_OBJECT *) ((u8 *) param_ptr +
				  param_length);

		/*
		 * Init the param array of pointers and NULL terminate
		 * the list
		 */

		for (i = 0; i < count; i++) {
			param_ptr[i] = &object_ptr[i];
			acpi_cm_init_static_object (&object_ptr[i]);
		}
		param_ptr[count] = NULL;

		/*
		 * Convert each external object in the list to an
		 * internal object
		 */
		for (i = 0; i < count; i++) {
			status =
				acpi_cm_build_internal_object (&param_objects->pointer[i],
						  param_ptr[i]);

			if (ACPI_FAILURE (status)) {
				acpi_cm_delete_internal_object_list (param_ptr);
				return (status);
			}
		}
	}


	/*
	 * Three major cases:
	 * 1) Fully qualified pathname
	 * 2) No handle, not fully qualified pathname (error)
	 * 3) Valid handle
	 */

	if ((pathname) &&
		(acpi_ns_valid_root_prefix (pathname[0])))
	{
		/*
		 *  The path is fully qualified, just evaluate by name
		 */
		status = acpi_ns_evaluate_by_name (pathname, param_ptr, &return_obj);
	}

	else if (!handle) {
		/*
		 * A handle is optional iff a fully qualified pathname
		 * is specified.  Since we've already handled fully
		 * qualified names above, this is an error
		 */



		status = AE_BAD_PARAMETER;
	}

	else {
		/*
		 * We get here if we have a handle -- and if we have a
		 * pathname it is relative.  The handle will be validated
		 * in the lower procedures
		 */

		if (!pathname) {
			/*
			 * The null pathname case means the handle is for
			 * the actual object to be evaluated
			 */
			status = acpi_ns_evaluate_by_handle (handle, param_ptr, &return_obj);
		}

		else {
		   /*
			* Both a Handle and a relative Pathname
			*/
			status = acpi_ns_evaluate_relative (handle, pathname, param_ptr,
					 &return_obj);
		}
	}


	/*
	 * If we are expecting a return value, and all went well above,
	 * copy the return value to an external object.
	 */

	if (return_buffer) {
		user_buffer_length = return_buffer->length;
		return_buffer->length = 0;

		if (return_obj) {
			if (VALID_DESCRIPTOR_TYPE (return_obj, ACPI_DESC_TYPE_NAMED)) {
				/*
				 * If we got an Node as a return object,
				 * this means the object we are evaluating
				 * has nothing interesting to return (such
				 * as a mutex, etc.)  We return an error
				 * because these types are essentially
				 * unsupported by this interface.  We
				 * don't check up front because this makes
				 * it easier to add support for various
				 * types at a later date if necessary.
				 */
				status = AE_TYPE;
				return_obj = NULL;  /* No need to delete an Node */
			}

			if (ACPI_SUCCESS (status)) {
				/*
				 * Find out how large a buffer is needed
				 * to contain the returned object
				 */
				status = acpi_cm_get_object_size (return_obj,
						   &buffer_space_needed);
				if (ACPI_SUCCESS (status)) {
					/*
					 * Check if there is enough room in the
					 * caller's buffer
					 */

					if (user_buffer_length < buffer_space_needed) {
						/*
						 * Caller's buffer is too small, can't
						 * give him partial results fail the call
						 * but return the buffer size needed
						 */

						return_buffer->length = buffer_space_needed;
						status = AE_BUFFER_OVERFLOW;
					}

					else {
						/*
						 *  We have enough space for the object, build it
						 */
						status = acpi_cm_build_external_object (return_obj,
								  return_buffer);
						return_buffer->length = buffer_space_needed;
					}
				}
			}
		}
	}


	/* Delete the return and parameter objects */

	if (return_obj) {
		/*
		 * Delete the internal return object. (Or at least
		 * decrement the reference count by one)
		 */
		acpi_cm_remove_reference (return_obj);
	}

	/*
	 * Free the input parameter list (if we created one),
	 */

	if (param_ptr) {
		/* Free the allocated parameter block */

		acpi_cm_delete_internal_object_list (param_ptr);
	}

	return (status);
}