195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
229a241ccSBob Moore /******************************************************************************
329a241ccSBob Moore  *
429a241ccSBob Moore  * Module Name: nsarguments - Validation of args for ACPI predefined methods
529a241ccSBob Moore  *
6*612c2932SBob Moore  * Copyright (C) 2000 - 2023, Intel Corp.
729a241ccSBob Moore  *
895857638SErik Schmauss  *****************************************************************************/
929a241ccSBob Moore 
1029a241ccSBob Moore #include <acpi/acpi.h>
1129a241ccSBob Moore #include "accommon.h"
1229a241ccSBob Moore #include "acnamesp.h"
1329a241ccSBob Moore #include "acpredef.h"
1429a241ccSBob Moore 
1529a241ccSBob Moore #define _COMPONENT          ACPI_NAMESPACE
1629a241ccSBob Moore ACPI_MODULE_NAME("nsarguments")
1729a241ccSBob Moore 
1829a241ccSBob Moore /*******************************************************************************
1929a241ccSBob Moore  *
2029a241ccSBob Moore  * FUNCTION:    acpi_ns_check_argument_types
2129a241ccSBob Moore  *
2229a241ccSBob Moore  * PARAMETERS:  info            - Method execution information block
2329a241ccSBob Moore  *
2429a241ccSBob Moore  * RETURN:      None
2529a241ccSBob Moore  *
2629a241ccSBob Moore  * DESCRIPTION: Check the incoming argument count and all argument types
2729a241ccSBob Moore  *              against the argument type list for a predefined name.
2829a241ccSBob Moore  *
2929a241ccSBob Moore  ******************************************************************************/
acpi_ns_check_argument_types(struct acpi_evaluate_info * info)3029a241ccSBob Moore void acpi_ns_check_argument_types(struct acpi_evaluate_info *info)
3129a241ccSBob Moore {
3229a241ccSBob Moore 	u16 arg_type_list;
3329a241ccSBob Moore 	u8 arg_count;
3429a241ccSBob Moore 	u8 arg_type;
3529a241ccSBob Moore 	u8 user_arg_type;
3629a241ccSBob Moore 	u32 i;
3729a241ccSBob Moore 
38a62a7117SBob Moore 	/*
39a62a7117SBob Moore 	 * If not a predefined name, cannot typecheck args, because
40a62a7117SBob Moore 	 * we have no idea what argument types are expected.
41a62a7117SBob Moore 	 * Also, ignore typecheck if warnings/errors if this method
42a62a7117SBob Moore 	 * has already been evaluated at least once -- in order
43a62a7117SBob Moore 	 * to suppress repetitive messages.
44a62a7117SBob Moore 	 */
45a62a7117SBob Moore 	if (!info->predefined || (info->node->flags & ANOBJ_EVALUATED)) {
4629a241ccSBob Moore 		return;
4729a241ccSBob Moore 	}
4829a241ccSBob Moore 
4929a241ccSBob Moore 	arg_type_list = info->predefined->info.argument_list;
5029a241ccSBob Moore 	arg_count = METHOD_GET_ARG_COUNT(arg_type_list);
5129a241ccSBob Moore 
5229a241ccSBob Moore 	/* Typecheck all arguments */
5329a241ccSBob Moore 
5429a241ccSBob Moore 	for (i = 0; ((i < arg_count) && (i < info->param_count)); i++) {
5529a241ccSBob Moore 		arg_type = METHOD_GET_NEXT_TYPE(arg_type_list);
5629a241ccSBob Moore 		user_arg_type = info->parameters[i]->common.type;
5729a241ccSBob Moore 
584d584037SBob Moore 		/* No typechecking for ACPI_TYPE_ANY */
594d584037SBob Moore 
604d584037SBob Moore 		if ((user_arg_type != arg_type) && (arg_type != ACPI_TYPE_ANY)) {
6129a241ccSBob Moore 			ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
6229a241ccSBob Moore 					      ACPI_WARN_ALWAYS,
6329a241ccSBob Moore 					      "Argument #%u type mismatch - "
6429a241ccSBob Moore 					      "Found [%s], ACPI requires [%s]",
6529a241ccSBob Moore 					      (i + 1),
6629a241ccSBob Moore 					      acpi_ut_get_type_name
6729a241ccSBob Moore 					      (user_arg_type),
6829a241ccSBob Moore 					      acpi_ut_get_type_name(arg_type)));
69a62a7117SBob Moore 
70a62a7117SBob Moore 			/* Prevent any additional typechecking for this method */
71a62a7117SBob Moore 
72a62a7117SBob Moore 			info->node->flags |= ANOBJ_EVALUATED;
7329a241ccSBob Moore 		}
7429a241ccSBob Moore 	}
7529a241ccSBob Moore }
7629a241ccSBob Moore 
7729a241ccSBob Moore /*******************************************************************************
7829a241ccSBob Moore  *
7929a241ccSBob Moore  * FUNCTION:    acpi_ns_check_acpi_compliance
8029a241ccSBob Moore  *
8129a241ccSBob Moore  * PARAMETERS:  pathname        - Full pathname to the node (for error msgs)
8229a241ccSBob Moore  *              node            - Namespace node for the method/object
8329a241ccSBob Moore  *              predefined      - Pointer to entry in predefined name table
8429a241ccSBob Moore  *
8529a241ccSBob Moore  * RETURN:      None
8629a241ccSBob Moore  *
8729a241ccSBob Moore  * DESCRIPTION: Check that the declared parameter count (in ASL/AML) for a
8829a241ccSBob Moore  *              predefined name is what is expected (matches what is defined in
8929a241ccSBob Moore  *              the ACPI specification for this predefined name.)
9029a241ccSBob Moore  *
9129a241ccSBob Moore  ******************************************************************************/
9229a241ccSBob Moore 
9329a241ccSBob Moore void
acpi_ns_check_acpi_compliance(char * pathname,struct acpi_namespace_node * node,const union acpi_predefined_info * predefined)9429a241ccSBob Moore acpi_ns_check_acpi_compliance(char *pathname,
9529a241ccSBob Moore 			      struct acpi_namespace_node *node,
9629a241ccSBob Moore 			      const union acpi_predefined_info *predefined)
9729a241ccSBob Moore {
9829a241ccSBob Moore 	u32 aml_param_count;
9929a241ccSBob Moore 	u32 required_param_count;
10029a241ccSBob Moore 
101a62a7117SBob Moore 	if (!predefined || (node->flags & ANOBJ_EVALUATED)) {
10229a241ccSBob Moore 		return;
10329a241ccSBob Moore 	}
10429a241ccSBob Moore 
10529a241ccSBob Moore 	/* Get the ACPI-required arg count from the predefined info table */
10629a241ccSBob Moore 
10729a241ccSBob Moore 	required_param_count =
10829a241ccSBob Moore 	    METHOD_GET_ARG_COUNT(predefined->info.argument_list);
10929a241ccSBob Moore 
11029a241ccSBob Moore 	/*
11129a241ccSBob Moore 	 * If this object is not a control method, we can check if the ACPI
11229a241ccSBob Moore 	 * spec requires that it be a method.
11329a241ccSBob Moore 	 */
11429a241ccSBob Moore 	if (node->type != ACPI_TYPE_METHOD) {
11529a241ccSBob Moore 		if (required_param_count > 0) {
11629a241ccSBob Moore 
11729a241ccSBob Moore 			/* Object requires args, must be implemented as a method */
11829a241ccSBob Moore 
11929a241ccSBob Moore 			ACPI_BIOS_ERROR_PREDEFINED((AE_INFO, pathname,
12029a241ccSBob Moore 						    ACPI_WARN_ALWAYS,
12129a241ccSBob Moore 						    "Object (%s) must be a control method with %u arguments",
12229a241ccSBob Moore 						    acpi_ut_get_type_name(node->
12329a241ccSBob Moore 									  type),
12429a241ccSBob Moore 						    required_param_count));
12529a241ccSBob Moore 		} else if (!required_param_count
12629a241ccSBob Moore 			   && !predefined->info.expected_btypes) {
12729a241ccSBob Moore 
12829a241ccSBob Moore 			/* Object requires no args and no return value, must be a method */
12929a241ccSBob Moore 
13029a241ccSBob Moore 			ACPI_BIOS_ERROR_PREDEFINED((AE_INFO, pathname,
13129a241ccSBob Moore 						    ACPI_WARN_ALWAYS,
13229a241ccSBob Moore 						    "Object (%s) must be a control method "
13329a241ccSBob Moore 						    "with no arguments and no return value",
13429a241ccSBob Moore 						    acpi_ut_get_type_name(node->
13529a241ccSBob Moore 									  type)));
13629a241ccSBob Moore 		}
13729a241ccSBob Moore 
13829a241ccSBob Moore 		return;
13929a241ccSBob Moore 	}
14029a241ccSBob Moore 
14129a241ccSBob Moore 	/*
14229a241ccSBob Moore 	 * This is a control method.
14329a241ccSBob Moore 	 * Check that the ASL/AML-defined parameter count for this method
14429a241ccSBob Moore 	 * matches the ACPI-required parameter count
14529a241ccSBob Moore 	 *
14629a241ccSBob Moore 	 * Some methods are allowed to have a "minimum" number of args (_SCP)
14729a241ccSBob Moore 	 * because their definition in ACPI has changed over time.
14829a241ccSBob Moore 	 *
14929a241ccSBob Moore 	 * Note: These are BIOS errors in the declaration of the object
15029a241ccSBob Moore 	 */
15129a241ccSBob Moore 	aml_param_count = node->object->method.param_count;
15229a241ccSBob Moore 
15329a241ccSBob Moore 	if (aml_param_count < required_param_count) {
15429a241ccSBob Moore 		ACPI_BIOS_ERROR_PREDEFINED((AE_INFO, pathname, ACPI_WARN_ALWAYS,
15529a241ccSBob Moore 					    "Insufficient arguments - "
15629a241ccSBob Moore 					    "ASL declared %u, ACPI requires %u",
15729a241ccSBob Moore 					    aml_param_count,
15829a241ccSBob Moore 					    required_param_count));
15929a241ccSBob Moore 	} else if ((aml_param_count > required_param_count)
16029a241ccSBob Moore 		   && !(predefined->info.
16129a241ccSBob Moore 			argument_list & ARG_COUNT_IS_MINIMUM)) {
16229a241ccSBob Moore 		ACPI_BIOS_ERROR_PREDEFINED((AE_INFO, pathname, ACPI_WARN_ALWAYS,
16329a241ccSBob Moore 					    "Excess arguments - "
16429a241ccSBob Moore 					    "ASL declared %u, ACPI requires %u",
16529a241ccSBob Moore 					    aml_param_count,
16629a241ccSBob Moore 					    required_param_count));
16729a241ccSBob Moore 	}
16829a241ccSBob Moore }
16929a241ccSBob Moore 
17029a241ccSBob Moore /*******************************************************************************
17129a241ccSBob Moore  *
17229a241ccSBob Moore  * FUNCTION:    acpi_ns_check_argument_count
17329a241ccSBob Moore  *
17429a241ccSBob Moore  * PARAMETERS:  pathname        - Full pathname to the node (for error msgs)
17529a241ccSBob Moore  *              node            - Namespace node for the method/object
17629a241ccSBob Moore  *              user_param_count - Number of args passed in by the caller
17729a241ccSBob Moore  *              predefined      - Pointer to entry in predefined name table
17829a241ccSBob Moore  *
17929a241ccSBob Moore  * RETURN:      None
18029a241ccSBob Moore  *
18129a241ccSBob Moore  * DESCRIPTION: Check that incoming argument count matches the declared
18229a241ccSBob Moore  *              parameter count (in the ASL/AML) for an object.
18329a241ccSBob Moore  *
18429a241ccSBob Moore  ******************************************************************************/
18529a241ccSBob Moore 
18629a241ccSBob Moore void
acpi_ns_check_argument_count(char * pathname,struct acpi_namespace_node * node,u32 user_param_count,const union acpi_predefined_info * predefined)18729a241ccSBob Moore acpi_ns_check_argument_count(char *pathname,
18829a241ccSBob Moore 			     struct acpi_namespace_node *node,
18929a241ccSBob Moore 			     u32 user_param_count,
19029a241ccSBob Moore 			     const union acpi_predefined_info *predefined)
19129a241ccSBob Moore {
19229a241ccSBob Moore 	u32 aml_param_count;
19329a241ccSBob Moore 	u32 required_param_count;
19429a241ccSBob Moore 
195a62a7117SBob Moore 	if (node->flags & ANOBJ_EVALUATED) {
196a62a7117SBob Moore 		return;
197a62a7117SBob Moore 	}
198a62a7117SBob Moore 
19929a241ccSBob Moore 	if (!predefined) {
20029a241ccSBob Moore 		/*
20129a241ccSBob Moore 		 * Not a predefined name. Check the incoming user argument count
20229a241ccSBob Moore 		 * against the count that is specified in the method/object.
20329a241ccSBob Moore 		 */
20429a241ccSBob Moore 		if (node->type != ACPI_TYPE_METHOD) {
20529a241ccSBob Moore 			if (user_param_count) {
20629a241ccSBob Moore 				ACPI_INFO_PREDEFINED((AE_INFO, pathname,
20729a241ccSBob Moore 						      ACPI_WARN_ALWAYS,
20829a241ccSBob Moore 						      "%u arguments were passed to a non-method ACPI object (%s)",
20929a241ccSBob Moore 						      user_param_count,
21029a241ccSBob Moore 						      acpi_ut_get_type_name
21129a241ccSBob Moore 						      (node->type)));
21229a241ccSBob Moore 			}
21329a241ccSBob Moore 
21429a241ccSBob Moore 			return;
21529a241ccSBob Moore 		}
21629a241ccSBob Moore 
21729a241ccSBob Moore 		/*
21829a241ccSBob Moore 		 * This is a control method. Check the parameter count.
21929a241ccSBob Moore 		 * We can only check the incoming argument count against the
22029a241ccSBob Moore 		 * argument count declared for the method in the ASL/AML.
22129a241ccSBob Moore 		 *
22229a241ccSBob Moore 		 * Emit a message if too few or too many arguments have been passed
22329a241ccSBob Moore 		 * by the caller.
22429a241ccSBob Moore 		 *
22529a241ccSBob Moore 		 * Note: Too many arguments will not cause the method to
22629a241ccSBob Moore 		 * fail. However, the method will fail if there are too few
22729a241ccSBob Moore 		 * arguments and the method attempts to use one of the missing ones.
22829a241ccSBob Moore 		 */
22929a241ccSBob Moore 		aml_param_count = node->object->method.param_count;
23029a241ccSBob Moore 
23129a241ccSBob Moore 		if (user_param_count < aml_param_count) {
23229a241ccSBob Moore 			ACPI_WARN_PREDEFINED((AE_INFO, pathname,
23329a241ccSBob Moore 					      ACPI_WARN_ALWAYS,
23429a241ccSBob Moore 					      "Insufficient arguments - "
23529a241ccSBob Moore 					      "Caller passed %u, method requires %u",
23629a241ccSBob Moore 					      user_param_count,
23729a241ccSBob Moore 					      aml_param_count));
23829a241ccSBob Moore 		} else if (user_param_count > aml_param_count) {
23929a241ccSBob Moore 			ACPI_INFO_PREDEFINED((AE_INFO, pathname,
24029a241ccSBob Moore 					      ACPI_WARN_ALWAYS,
24129a241ccSBob Moore 					      "Excess arguments - "
24229a241ccSBob Moore 					      "Caller passed %u, method requires %u",
24329a241ccSBob Moore 					      user_param_count,
24429a241ccSBob Moore 					      aml_param_count));
24529a241ccSBob Moore 		}
24629a241ccSBob Moore 
24729a241ccSBob Moore 		return;
24829a241ccSBob Moore 	}
24929a241ccSBob Moore 
25029a241ccSBob Moore 	/*
25129a241ccSBob Moore 	 * This is a predefined name. Validate the user-supplied parameter
25229a241ccSBob Moore 	 * count against the ACPI specification. We don't validate against
25329a241ccSBob Moore 	 * the method itself because what is important here is that the
25429a241ccSBob Moore 	 * caller is in conformance with the spec. (The arg count for the
25529a241ccSBob Moore 	 * method was checked against the ACPI spec earlier.)
25629a241ccSBob Moore 	 *
25729a241ccSBob Moore 	 * Some methods are allowed to have a "minimum" number of args (_SCP)
25829a241ccSBob Moore 	 * because their definition in ACPI has changed over time.
25929a241ccSBob Moore 	 */
26029a241ccSBob Moore 	required_param_count =
26129a241ccSBob Moore 	    METHOD_GET_ARG_COUNT(predefined->info.argument_list);
26229a241ccSBob Moore 
26329a241ccSBob Moore 	if (user_param_count < required_param_count) {
26429a241ccSBob Moore 		ACPI_WARN_PREDEFINED((AE_INFO, pathname, ACPI_WARN_ALWAYS,
26529a241ccSBob Moore 				      "Insufficient arguments - "
26629a241ccSBob Moore 				      "Caller passed %u, ACPI requires %u",
26729a241ccSBob Moore 				      user_param_count, required_param_count));
26829a241ccSBob Moore 	} else if ((user_param_count > required_param_count) &&
26929a241ccSBob Moore 		   !(predefined->info.argument_list & ARG_COUNT_IS_MINIMUM)) {
27029a241ccSBob Moore 		ACPI_INFO_PREDEFINED((AE_INFO, pathname, ACPI_WARN_ALWAYS,
27129a241ccSBob Moore 				      "Excess arguments - "
27229a241ccSBob Moore 				      "Caller passed %u, ACPI requires %u",
27329a241ccSBob Moore 				      user_param_count, required_param_count));
27429a241ccSBob Moore 	}
27529a241ccSBob Moore }
276