276 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/******************************************************************************3 *4 * Module Name: nsarguments - Validation of args for ACPI predefined methods5 *6 * Copyright (C) 2000 - 2023, Intel Corp.7 *8 *****************************************************************************/9 10#include <acpi/acpi.h>11#include "accommon.h"12#include "acnamesp.h"13#include "acpredef.h"14 15#define _COMPONENT ACPI_NAMESPACE16ACPI_MODULE_NAME("nsarguments")17 18/*******************************************************************************19 *20 * FUNCTION: acpi_ns_check_argument_types21 *22 * PARAMETERS: info - Method execution information block23 *24 * RETURN: None25 *26 * DESCRIPTION: Check the incoming argument count and all argument types27 * against the argument type list for a predefined name.28 *29 ******************************************************************************/30void acpi_ns_check_argument_types(struct acpi_evaluate_info *info)31{32 u16 arg_type_list;33 u8 arg_count;34 u8 arg_type;35 u8 user_arg_type;36 u32 i;37 38 /*39 * If not a predefined name, cannot typecheck args, because40 * we have no idea what argument types are expected.41 * Also, ignore typecheck if warnings/errors if this method42 * has already been evaluated at least once -- in order43 * to suppress repetitive messages.44 */45 if (!info->predefined || (info->node->flags & ANOBJ_EVALUATED)) {46 return;47 }48 49 arg_type_list = info->predefined->info.argument_list;50 arg_count = METHOD_GET_ARG_COUNT(arg_type_list);51 52 /* Typecheck all arguments */53 54 for (i = 0; ((i < arg_count) && (i < info->param_count)); i++) {55 arg_type = METHOD_GET_NEXT_TYPE(arg_type_list);56 user_arg_type = info->parameters[i]->common.type;57 58 /* No typechecking for ACPI_TYPE_ANY */59 60 if ((user_arg_type != arg_type) && (arg_type != ACPI_TYPE_ANY)) {61 ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,62 ACPI_WARN_ALWAYS,63 "Argument #%u type mismatch - "64 "Found [%s], ACPI requires [%s]",65 (i + 1),66 acpi_ut_get_type_name67 (user_arg_type),68 acpi_ut_get_type_name(arg_type)));69 70 /* Prevent any additional typechecking for this method */71 72 info->node->flags |= ANOBJ_EVALUATED;73 }74 }75}76 77/*******************************************************************************78 *79 * FUNCTION: acpi_ns_check_acpi_compliance80 *81 * PARAMETERS: pathname - Full pathname to the node (for error msgs)82 * node - Namespace node for the method/object83 * predefined - Pointer to entry in predefined name table84 *85 * RETURN: None86 *87 * DESCRIPTION: Check that the declared parameter count (in ASL/AML) for a88 * predefined name is what is expected (matches what is defined in89 * the ACPI specification for this predefined name.)90 *91 ******************************************************************************/92 93void94acpi_ns_check_acpi_compliance(char *pathname,95 struct acpi_namespace_node *node,96 const union acpi_predefined_info *predefined)97{98 u32 aml_param_count;99 u32 required_param_count;100 101 if (!predefined || (node->flags & ANOBJ_EVALUATED)) {102 return;103 }104 105 /* Get the ACPI-required arg count from the predefined info table */106 107 required_param_count =108 METHOD_GET_ARG_COUNT(predefined->info.argument_list);109 110 /*111 * If this object is not a control method, we can check if the ACPI112 * spec requires that it be a method.113 */114 if (node->type != ACPI_TYPE_METHOD) {115 if (required_param_count > 0) {116 117 /* Object requires args, must be implemented as a method */118 119 ACPI_BIOS_ERROR_PREDEFINED((AE_INFO, pathname,120 ACPI_WARN_ALWAYS,121 "Object (%s) must be a control method with %u arguments",122 acpi_ut_get_type_name(node->123 type),124 required_param_count));125 } else if (!required_param_count126 && !predefined->info.expected_btypes) {127 128 /* Object requires no args and no return value, must be a method */129 130 ACPI_BIOS_ERROR_PREDEFINED((AE_INFO, pathname,131 ACPI_WARN_ALWAYS,132 "Object (%s) must be a control method "133 "with no arguments and no return value",134 acpi_ut_get_type_name(node->135 type)));136 }137 138 return;139 }140 141 /*142 * This is a control method.143 * Check that the ASL/AML-defined parameter count for this method144 * matches the ACPI-required parameter count145 *146 * Some methods are allowed to have a "minimum" number of args (_SCP)147 * because their definition in ACPI has changed over time.148 *149 * Note: These are BIOS errors in the declaration of the object150 */151 aml_param_count = node->object->method.param_count;152 153 if (aml_param_count < required_param_count) {154 ACPI_BIOS_ERROR_PREDEFINED((AE_INFO, pathname, ACPI_WARN_ALWAYS,155 "Insufficient arguments - "156 "ASL declared %u, ACPI requires %u",157 aml_param_count,158 required_param_count));159 } else if ((aml_param_count > required_param_count)160 && !(predefined->info.161 argument_list & ARG_COUNT_IS_MINIMUM)) {162 ACPI_BIOS_ERROR_PREDEFINED((AE_INFO, pathname, ACPI_WARN_ALWAYS,163 "Excess arguments - "164 "ASL declared %u, ACPI requires %u",165 aml_param_count,166 required_param_count));167 }168}169 170/*******************************************************************************171 *172 * FUNCTION: acpi_ns_check_argument_count173 *174 * PARAMETERS: pathname - Full pathname to the node (for error msgs)175 * node - Namespace node for the method/object176 * user_param_count - Number of args passed in by the caller177 * predefined - Pointer to entry in predefined name table178 *179 * RETURN: None180 *181 * DESCRIPTION: Check that incoming argument count matches the declared182 * parameter count (in the ASL/AML) for an object.183 *184 ******************************************************************************/185 186void187acpi_ns_check_argument_count(char *pathname,188 struct acpi_namespace_node *node,189 u32 user_param_count,190 const union acpi_predefined_info *predefined)191{192 u32 aml_param_count;193 u32 required_param_count;194 195 if (node->flags & ANOBJ_EVALUATED) {196 return;197 }198 199 if (!predefined) {200 /*201 * Not a predefined name. Check the incoming user argument count202 * against the count that is specified in the method/object.203 */204 if (node->type != ACPI_TYPE_METHOD) {205 if (user_param_count) {206 ACPI_INFO_PREDEFINED((AE_INFO, pathname,207 ACPI_WARN_ALWAYS,208 "%u arguments were passed to a non-method ACPI object (%s)",209 user_param_count,210 acpi_ut_get_type_name211 (node->type)));212 }213 214 return;215 }216 217 /*218 * This is a control method. Check the parameter count.219 * We can only check the incoming argument count against the220 * argument count declared for the method in the ASL/AML.221 *222 * Emit a message if too few or too many arguments have been passed223 * by the caller.224 *225 * Note: Too many arguments will not cause the method to226 * fail. However, the method will fail if there are too few227 * arguments and the method attempts to use one of the missing ones.228 */229 aml_param_count = node->object->method.param_count;230 231 if (user_param_count < aml_param_count) {232 ACPI_WARN_PREDEFINED((AE_INFO, pathname,233 ACPI_WARN_ALWAYS,234 "Insufficient arguments - "235 "Caller passed %u, method requires %u",236 user_param_count,237 aml_param_count));238 } else if (user_param_count > aml_param_count) {239 ACPI_INFO_PREDEFINED((AE_INFO, pathname,240 ACPI_WARN_ALWAYS,241 "Excess arguments - "242 "Caller passed %u, method requires %u",243 user_param_count,244 aml_param_count));245 }246 247 return;248 }249 250 /*251 * This is a predefined name. Validate the user-supplied parameter252 * count against the ACPI specification. We don't validate against253 * the method itself because what is important here is that the254 * caller is in conformance with the spec. (The arg count for the255 * method was checked against the ACPI spec earlier.)256 *257 * Some methods are allowed to have a "minimum" number of args (_SCP)258 * because their definition in ACPI has changed over time.259 */260 required_param_count =261 METHOD_GET_ARG_COUNT(predefined->info.argument_list);262 263 if (user_param_count < required_param_count) {264 ACPI_WARN_PREDEFINED((AE_INFO, pathname, ACPI_WARN_ALWAYS,265 "Insufficient arguments - "266 "Caller passed %u, ACPI requires %u",267 user_param_count, required_param_count));268 } else if ((user_param_count > required_param_count) &&269 !(predefined->info.argument_list & ARG_COUNT_IS_MINIMUM)) {270 ACPI_INFO_PREDEFINED((AE_INFO, pathname, ACPI_WARN_ALWAYS,271 "Excess arguments - "272 "Caller passed %u, ACPI requires %u",273 user_param_count, required_param_count));274 }275}276