Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eeb4437e authored by Bob Moore's avatar Bob Moore Committed by Len Brown
Browse files

ACPICA: Consolidate method arg count validation code



Merge the code that validates control method argument counts into
the predefined validation module. Eliminates possible multiple
warnings for incorrect counts.

Signed-off-by: default avatarBob Moore <robert.moore@intel.com>
Signed-off-by: default avatarLin Ming <ming.m.lin@intel.com>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent a647b5c3
Loading
Loading
Loading
Loading
+14 −55
Original line number Diff line number Diff line
@@ -89,6 +89,7 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
	/* Initialize the return value to an invalid object */

	info->return_object = NULL;
	info->param_count = 0;

	/*
	 * Get the actual namespace node for the target object. Handles these cases:
@@ -141,42 +142,18 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
			return_ACPI_STATUS(AE_NULL_OBJECT);
		}

		/*
		 * Calculate the number of arguments being passed to the method
		 */
		/* Count the number of arguments being passed to the method */

		info->param_count = 0;
		if (info->parameters) {
			while (info->parameters[info->param_count])
			while (info->parameters[info->param_count]) {
				if (info->param_count > ACPI_METHOD_MAX_ARG) {
					return_ACPI_STATUS(AE_LIMIT);
				}
				info->param_count++;
			}

		/*
		 * Warning if too few or too many arguments have been passed by the
		 * caller. We don't want to abort here with an error because an
		 * incorrect number of arguments may not cause the method to fail.
		 * However, the method will fail if there are too few arguments passed
		 * and the method attempts to use one of the missing ones.
		 */

		if (info->param_count < info->obj_desc->method.param_count) {
			ACPI_WARNING((AE_INFO,
				    "Insufficient arguments - "
				    "method [%4.4s] needs %d, found %d",
				    acpi_ut_get_node_name(info->resolved_node),
				    info->obj_desc->method.param_count,
				    info->param_count));
		} else if (info->param_count >
				info->obj_desc->method.param_count) {
			ACPI_WARNING((AE_INFO,
				      "Excess arguments - "
				      "method [%4.4s] needs %d, found %d",
				      acpi_ut_get_node_name(info->
							    resolved_node),
				      info->obj_desc->method.param_count,
				      info->param_count));
		}


		ACPI_DUMP_PATHNAME(info->resolved_node, "Execute Method:",
				   ACPI_LV_INFO, _COMPONENT);

@@ -264,31 +241,13 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
		}
	}

	/* Validation of return values for ACPI-predefined methods and objects */

	if ((status == AE_OK) || (status == AE_CTRL_RETURN_VALUE)) {
	/*
		 * If this is the first evaluation, check the return value. This
		 * ensures that any warnings will only be emitted during the very
		 * first evaluation of the object.
		 */
		if (!(node->flags & ANOBJ_EVALUATED)) {
			/*
			 * Check for a predefined ACPI name. If found, validate the
			 * returned object.
			 *
			 * Note: Ignore return status for now, emit warnings if there are
			 * problems with the returned object. May change later to abort
			 * the method on invalid return object.
	 * Check input argument count against the ASL-defined count for a method.
	 * Also check predefined names: argument count and return value against
	 * the ACPI specification. Some incorrect return value types are repaired.
	 */
			(void)acpi_ns_check_predefined_names(node,
			     &info->return_object);
		}

		/* Mark the node as having been evaluated */

		node->flags |= ANOBJ_EVALUATED;
	}
	(void)acpi_ns_check_predefined_names(node, info->param_count,
		status, &info->return_object);

	/* Check if there is a return value that must be dealt with */

+87 −19
Original line number Diff line number Diff line
@@ -124,6 +124,8 @@ static const char *acpi_rtype_names[] = {

acpi_status
acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
			       u32 user_param_count,
			       acpi_status return_status,
			       union acpi_operand_object **return_object_ptr)
{
	union acpi_operand_object *return_object = *return_object_ptr;
@@ -134,12 +136,6 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
	/* Match the name for this method/object against the predefined list */

	predefined = acpi_ns_check_for_predefined_name(node);
	if (!predefined) {

		/* Name was not one of the predefined names */

		return (AE_OK);
	}

	/* Get the full pathname to the object, for use in error messages */

@@ -149,10 +145,37 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
	}

	/*
	 * Check that the parameter count for this method is in accordance
	 * with the ACPI specification.
	 * Check that the parameter count for this method matches the ASL
	 * definition. For predefined names, ensure that both the caller and
	 * the method itself are in accordance with the ACPI specification.
	 */
	acpi_ns_check_parameter_count(pathname, node, user_param_count,
				      predefined);

	/* If not a predefined name, we cannot validate the return object */

	if (!predefined) {
		goto exit;
	}

	/* If the method failed, we cannot validate the return object */

	if ((return_status != AE_OK) && (return_status != AE_CTRL_RETURN_VALUE)) {
		goto exit;
	}

	/*
	 * Only validate the return value on the first successful evaluation of
	 * the method. This ensures that any warnings will only be emitted during
	 * the very first evaluation of the method/object.
	 */
	acpi_ns_check_parameter_count(pathname, node, predefined);
	if (node->flags & ANOBJ_EVALUATED) {
		goto exit;
	}

	/* Mark the node as having been successfully evaluated */

	node->flags |= ANOBJ_EVALUATED;

	/*
	 * If there is no return value, check if we require a return value for
@@ -177,7 +200,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
	 * We have a return value, but if one wasn't expected, just exit, this is
	 * not a problem
	 *
	 * For example, if "Implicit return value" is enabled, methods will
	 * For example, if the "Implicit Return" feature is enabled, methods will
	 * always return a value
	 */
	if (!predefined->info.expected_btypes) {
@@ -204,7 +227,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
	}

      exit:
	if (pathname) {
	if (pathname != predefined->info.name) {
		ACPI_FREE(pathname);
	}

@@ -217,6 +240,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
 *
 * PARAMETERS:  Pathname        - Full pathname to the node (for error msgs)
 *              Node            - Namespace node for the method/object
 *              user_param_count - Number of args passed in by the caller
 *              Predefined      - Pointer to entry in predefined name table
 *
 * RETURN:      None
@@ -230,32 +254,76 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
void
acpi_ns_check_parameter_count(char *pathname,
			      struct acpi_namespace_node *node,
			      u32 user_param_count,
			      const union acpi_predefined_info *predefined)
{
	u32 param_count;
	u32 required_params_current;
	u32 required_params_old;

	/*
	 * Check that the ASL-defined parameter count is what is expected for
	 * this predefined name.
	 *
	 * Methods have 0-7 parameters. All other types have zero.
	 */
	/* Methods have 0-7 parameters. All other types have zero. */

	param_count = 0;
	if (node->type == ACPI_TYPE_METHOD) {
		param_count = node->object->method.param_count;
	}

	/* Validate parameter count - allow two different legal counts (_SCP) */
	/* Argument count check for non-predefined methods/objects */

	if (!predefined) {
		/*
		 * Warning if too few or too many arguments have been passed by the
		 * caller. An incorrect number of arguments may not cause the method
		 * to fail. However, the method will fail if there are too few
		 * arguments and the method attempts to use one of the missing ones.
		 */
		if (user_param_count < param_count) {
			ACPI_WARNING((AE_INFO,
				      "%s: Insufficient arguments - needs %d, found %d",
				      pathname, param_count, user_param_count));
		} else if (user_param_count > param_count) {
			ACPI_WARNING((AE_INFO,
				      "%s: Excess arguments - needs %d, found %d",
				      pathname, param_count, user_param_count));
		}
		return;
	}

	/* Allow two different legal argument counts (_SCP, etc.) */

	required_params_current = predefined->info.param_count & 0x0F;
	required_params_old = predefined->info.param_count >> 4;

	if (user_param_count != ACPI_UINT32_MAX) {

		/* Validate the user-supplied parameter count */

		if ((user_param_count != required_params_current) &&
		    (user_param_count != required_params_old)) {
			ACPI_WARNING((AE_INFO,
				      "%s: Parameter count mismatch - caller passed %d, ACPI requires %d",
				      pathname, user_param_count,
				      required_params_current));
		}
	}

	/*
	 * Only validate the argument count on the first successful evaluation of
	 * the method. This ensures that any warnings will only be emitted during
	 * the very first evaluation of the method/object.
	 */
	if (node->flags & ANOBJ_EVALUATED) {
		return;
	}

	/*
	 * Check that the ASL-defined parameter count is what is expected for
	 * this predefined name.
	 */
	if ((param_count != required_params_current) &&
	    (param_count != required_params_old)) {
		ACPI_WARNING((AE_INFO,
			      "%s: Parameter count mismatch - ASL declared %d, expected %d",
			      "%s: Parameter count mismatch - ASL declared %d, ACPI requires %d",
			      pathname, param_count, required_params_current));
	}
}
+3 −0
Original line number Diff line number Diff line
@@ -182,6 +182,8 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info);
 */
acpi_status
acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
			       u32 user_param_count,
			       acpi_status return_status,
			       union acpi_operand_object **return_object);

const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct
@@ -191,6 +193,7 @@ const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct
void
acpi_ns_check_parameter_count(char *pathname,
			      struct acpi_namespace_node *node,
			      u32 user_param_count,
			      const union acpi_predefined_info *info);

/*