Пример #1
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_evaluate_object
 *
 * PARAMETERS:  Handle              - Object handle (optional)
 *              Pathname            - Object pathname (optional)
 *              external_params     - List of parameters to pass to method,
 *                                    terminated by NULL.  May be NULL
 *                                    if no parameters are being passed.
 *              return_buffer       - Where to put method's return value (if
 *                                    any).  If NULL, no value is returned.
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Find and evaluate the given object, passing the given
 *              parameters if necessary.  One of "Handle" or "Pathname" must
 *              be valid (non-null)
 *
 ******************************************************************************/
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;
	struct acpi_evaluate_info *info;
	acpi_size buffer_space_needed;
	u32 i;

	ACPI_FUNCTION_TRACE(acpi_evaluate_object);

	/* Allocate and initialize the evaluation information block */

	info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
	if (!info) {
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	info->pathname = pathname;
	info->parameter_type = ACPI_PARAM_ARGS;

	/* Convert and validate the device handle */

	info->prefix_node = acpi_ns_map_handle_to_node(handle);
	if (!info->prefix_node) {
		status = AE_BAD_PARAMETER;
		goto cleanup;
	}

	/*
	 * If there are parameters to be passed to a control method, the external
	 * objects must all 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_ALLOCATE_ZEROED(((acpi_size)
							 external_params->
							 count +
							 1) * sizeof(void *));
		if (!info->parameters) {
			status = AE_NO_MEMORY;
			goto cleanup;
		}

		/* 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)) {
				goto cleanup;
			}
		}
		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 */

		info->prefix_node = NULL;
		status = acpi_ns_evaluate(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_INFO,
					  "Both Handle and Pathname are NULL"));
		} else {
			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
					  "Null Handle with relative pathname [%s]",
					  pathname));
		}

		status = AE_BAD_PARAMETER;
	} else {
		/* We have a namespace a node and a possible relative path */

		status = acpi_ns_evaluate(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)) {

				/* Get the size of 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.
		 */
		acpi_ex_enter_interpreter();

		/* Remove one reference on the return object (should delete it) */

		acpi_ut_remove_reference(info->return_object);
		acpi_ex_exit_interpreter();
	}

      cleanup:

	/* 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);
	}

	ACPI_FREE(info);
	return_ACPI_STATUS(status);
}
Пример #2
0
acpi_status
acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
				 struct acpi_buffer *output_buffer)
{
	u8 *buffer;
	union acpi_operand_object **top_object_list;
	union acpi_operand_object **sub_object_list;
	union acpi_operand_object *obj_desc;
	acpi_size buffer_size_needed = 0;
	u32 number_of_elements;
	u32 index;
	struct acpi_pci_routing_table *user_prt;
	struct acpi_namespace_node *node;
	acpi_status status;
	struct acpi_buffer path_buffer;

	ACPI_FUNCTION_TRACE(rs_create_pci_routing_table);

	/* Params already validated, so we don't re-validate here */

	/* Get the required buffer length */

	status = acpi_rs_get_pci_routing_table_length(package_object,
						      &buffer_size_needed);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "BufferSizeNeeded = %X\n",
			  (u32) buffer_size_needed));

	/* Validate/Allocate/Clear caller buffer */

	status = acpi_ut_initialize_buffer(output_buffer, buffer_size_needed);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/*
	 * Loop through the ACPI_INTERNAL_OBJECTS - Each object
	 * should be a package that in turn contains an
	 * acpi_integer Address, a u8 Pin, a Name and a u8 source_index.
	 */
	top_object_list = package_object->package.elements;
	number_of_elements = package_object->package.count;
	buffer = output_buffer->pointer;
	user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer);

	for (index = 0; index < number_of_elements; index++) {
		/*
		 * Point user_prt past this current structure
		 *
		 * NOTE: On the first iteration, user_prt->Length will
		 * be zero because we cleared the return buffer earlier
		 */
		buffer += user_prt->length;
		user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer);

		/*
		 * Fill in the Length field with the information we have at this point.
		 * The minus four is to subtract the size of the u8 Source[4] member
		 * because it is added below.
		 */
		user_prt->length = (sizeof(struct acpi_pci_routing_table) - 4);

		/* Each element of the top-level package must also be a package */

		if (ACPI_GET_OBJECT_TYPE(*top_object_list) != ACPI_TYPE_PACKAGE) {
			ACPI_ERROR((AE_INFO,
				    "(PRT[%X]) Need sub-package, found %s",
				    index,
				    acpi_ut_get_object_type_name
				    (*top_object_list)));
			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
		}

		/* Each sub-package must be of length 4 */

		if ((*top_object_list)->package.count != 4) {
			ACPI_ERROR((AE_INFO,
				    "(PRT[%X]) Need package of length 4, found length %d",
				    index, (*top_object_list)->package.count));
			return_ACPI_STATUS(AE_AML_PACKAGE_LIMIT);
		}

		/*
		 * Dereference the sub-package.
		 * The sub_object_list will now point to an array of the four IRQ
		 * elements: [Address, Pin, Source, source_index]
		 */
		sub_object_list = (*top_object_list)->package.elements;

		/* 1) First subobject: Dereference the PRT.Address */

		obj_desc = sub_object_list[0];
		if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
			user_prt->address = obj_desc->integer.value;
		} else {
			ACPI_ERROR((AE_INFO,
				    "(PRT[%X].Address) Need Integer, found %s",
				    index,
				    acpi_ut_get_object_type_name(obj_desc)));
			return_ACPI_STATUS(AE_BAD_DATA);
		}

		/* 2) Second subobject: Dereference the PRT.Pin */

		obj_desc = sub_object_list[1];
		if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
			user_prt->pin = (u32) obj_desc->integer.value;
		} else {
			ACPI_ERROR((AE_INFO,
				    "(PRT[%X].Pin) Need Integer, found %s",
				    index,
				    acpi_ut_get_object_type_name(obj_desc)));
			return_ACPI_STATUS(AE_BAD_DATA);
		}

		/*
		 * 3) Third subobject: Dereference the PRT.source_name
		 * The name may be unresolved (slack mode), so allow a null object
		 */
		obj_desc = sub_object_list[2];
		if (obj_desc) {
			switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
			case ACPI_TYPE_LOCAL_REFERENCE:

				if (obj_desc->reference.opcode !=
				    AML_INT_NAMEPATH_OP) {
					ACPI_ERROR((AE_INFO,
						    "(PRT[%X].Source) Need name, found reference op %X",
						    index,
						    obj_desc->reference.
						    opcode));
					return_ACPI_STATUS(AE_BAD_DATA);
				}

				node = obj_desc->reference.node;

				/* Use *remaining* length of the buffer as max for pathname */

				path_buffer.length = output_buffer->length -
				    (u32) ((u8 *) user_prt->source -
					   (u8 *) output_buffer->pointer);
				path_buffer.pointer = user_prt->source;

				status =
				    acpi_ns_handle_to_pathname((acpi_handle)
							       node,
							       &path_buffer);

				/* +1 to include null terminator */

				user_prt->length +=
				    (u32) ACPI_STRLEN(user_prt->source) + 1;
				break;

			case ACPI_TYPE_STRING:

				ACPI_STRCPY(user_prt->source,
					    obj_desc->string.pointer);

				/*
				 * Add to the Length field the length of the string
				 * (add 1 for terminator)
				 */
				user_prt->length += obj_desc->string.length + 1;
				break;

			case ACPI_TYPE_INTEGER:
				/*
				 * If this is a number, then the Source Name is NULL, since the
				 * entire buffer was zeroed out, we can leave this alone.
				 *
				 * Add to the Length field the length of the u32 NULL
				 */
				user_prt->length += sizeof(u32);
				break;

			default:

				ACPI_ERROR((AE_INFO,
					    "(PRT[%X].Source) Need Ref/String/Integer, found %s",
					    index,
					    acpi_ut_get_object_type_name
					    (obj_desc)));
				return_ACPI_STATUS(AE_BAD_DATA);
			}
		}

		/* Now align the current length */

		user_prt->length =
		    (u32) ACPI_ROUND_UP_TO_64BIT(user_prt->length);

		/* 4) Fourth subobject: Dereference the PRT.source_index */

		obj_desc = sub_object_list[3];
		if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
			user_prt->source_index = (u32) obj_desc->integer.value;
		} else {
			ACPI_ERROR((AE_INFO,
				    "(PRT[%X].SourceIndex) Need Integer, found %s",
				    index,
				    acpi_ut_get_object_type_name(obj_desc)));
			return_ACPI_STATUS(AE_BAD_DATA);
		}

		/* Point to the next union acpi_operand_object in the top level package */

		top_object_list++;
	}

	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n",
			  output_buffer->pointer, (u32) output_buffer->length));
	return_ACPI_STATUS(AE_OK);
}