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