1 /****************************************************************************** 2 * 3 * Module Name: nsarguments - Validation of args for ACPI predefined methods 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2018, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #include <acpi/acpi.h> 45 #include "accommon.h" 46 #include "acnamesp.h" 47 #include "acpredef.h" 48 49 #define _COMPONENT ACPI_NAMESPACE 50 ACPI_MODULE_NAME("nsarguments") 51 52 /******************************************************************************* 53 * 54 * FUNCTION: acpi_ns_check_argument_types 55 * 56 * PARAMETERS: info - Method execution information block 57 * 58 * RETURN: None 59 * 60 * DESCRIPTION: Check the incoming argument count and all argument types 61 * against the argument type list for a predefined name. 62 * 63 ******************************************************************************/ 64 void acpi_ns_check_argument_types(struct acpi_evaluate_info *info) 65 { 66 u16 arg_type_list; 67 u8 arg_count; 68 u8 arg_type; 69 u8 user_arg_type; 70 u32 i; 71 72 /* 73 * If not a predefined name, cannot typecheck args, because 74 * we have no idea what argument types are expected. 75 * Also, ignore typecheck if warnings/errors if this method 76 * has already been evaluated at least once -- in order 77 * to suppress repetitive messages. 78 */ 79 if (!info->predefined || (info->node->flags & ANOBJ_EVALUATED)) { 80 return; 81 } 82 83 arg_type_list = info->predefined->info.argument_list; 84 arg_count = METHOD_GET_ARG_COUNT(arg_type_list); 85 86 /* Typecheck all arguments */ 87 88 for (i = 0; ((i < arg_count) && (i < info->param_count)); i++) { 89 arg_type = METHOD_GET_NEXT_TYPE(arg_type_list); 90 user_arg_type = info->parameters[i]->common.type; 91 92 if (user_arg_type != arg_type) { 93 ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, 94 ACPI_WARN_ALWAYS, 95 "Argument #%u type mismatch - " 96 "Found [%s], ACPI requires [%s]", 97 (i + 1), 98 acpi_ut_get_type_name 99 (user_arg_type), 100 acpi_ut_get_type_name(arg_type))); 101 102 /* Prevent any additional typechecking for this method */ 103 104 info->node->flags |= ANOBJ_EVALUATED; 105 } 106 } 107 } 108 109 /******************************************************************************* 110 * 111 * FUNCTION: acpi_ns_check_acpi_compliance 112 * 113 * PARAMETERS: pathname - Full pathname to the node (for error msgs) 114 * node - Namespace node for the method/object 115 * predefined - Pointer to entry in predefined name table 116 * 117 * RETURN: None 118 * 119 * DESCRIPTION: Check that the declared parameter count (in ASL/AML) for a 120 * predefined name is what is expected (matches what is defined in 121 * the ACPI specification for this predefined name.) 122 * 123 ******************************************************************************/ 124 125 void 126 acpi_ns_check_acpi_compliance(char *pathname, 127 struct acpi_namespace_node *node, 128 const union acpi_predefined_info *predefined) 129 { 130 u32 aml_param_count; 131 u32 required_param_count; 132 133 if (!predefined || (node->flags & ANOBJ_EVALUATED)) { 134 return; 135 } 136 137 /* Get the ACPI-required arg count from the predefined info table */ 138 139 required_param_count = 140 METHOD_GET_ARG_COUNT(predefined->info.argument_list); 141 142 /* 143 * If this object is not a control method, we can check if the ACPI 144 * spec requires that it be a method. 145 */ 146 if (node->type != ACPI_TYPE_METHOD) { 147 if (required_param_count > 0) { 148 149 /* Object requires args, must be implemented as a method */ 150 151 ACPI_BIOS_ERROR_PREDEFINED((AE_INFO, pathname, 152 ACPI_WARN_ALWAYS, 153 "Object (%s) must be a control method with %u arguments", 154 acpi_ut_get_type_name(node-> 155 type), 156 required_param_count)); 157 } else if (!required_param_count 158 && !predefined->info.expected_btypes) { 159 160 /* Object requires no args and no return value, must be a method */ 161 162 ACPI_BIOS_ERROR_PREDEFINED((AE_INFO, pathname, 163 ACPI_WARN_ALWAYS, 164 "Object (%s) must be a control method " 165 "with no arguments and no return value", 166 acpi_ut_get_type_name(node-> 167 type))); 168 } 169 170 return; 171 } 172 173 /* 174 * This is a control method. 175 * Check that the ASL/AML-defined parameter count for this method 176 * matches the ACPI-required parameter count 177 * 178 * Some methods are allowed to have a "minimum" number of args (_SCP) 179 * because their definition in ACPI has changed over time. 180 * 181 * Note: These are BIOS errors in the declaration of the object 182 */ 183 aml_param_count = node->object->method.param_count; 184 185 if (aml_param_count < required_param_count) { 186 ACPI_BIOS_ERROR_PREDEFINED((AE_INFO, pathname, ACPI_WARN_ALWAYS, 187 "Insufficient arguments - " 188 "ASL declared %u, ACPI requires %u", 189 aml_param_count, 190 required_param_count)); 191 } else if ((aml_param_count > required_param_count) 192 && !(predefined->info. 193 argument_list & ARG_COUNT_IS_MINIMUM)) { 194 ACPI_BIOS_ERROR_PREDEFINED((AE_INFO, pathname, ACPI_WARN_ALWAYS, 195 "Excess arguments - " 196 "ASL declared %u, ACPI requires %u", 197 aml_param_count, 198 required_param_count)); 199 } 200 } 201 202 /******************************************************************************* 203 * 204 * FUNCTION: acpi_ns_check_argument_count 205 * 206 * PARAMETERS: pathname - Full pathname to the node (for error msgs) 207 * node - Namespace node for the method/object 208 * user_param_count - Number of args passed in by the caller 209 * predefined - Pointer to entry in predefined name table 210 * 211 * RETURN: None 212 * 213 * DESCRIPTION: Check that incoming argument count matches the declared 214 * parameter count (in the ASL/AML) for an object. 215 * 216 ******************************************************************************/ 217 218 void 219 acpi_ns_check_argument_count(char *pathname, 220 struct acpi_namespace_node *node, 221 u32 user_param_count, 222 const union acpi_predefined_info *predefined) 223 { 224 u32 aml_param_count; 225 u32 required_param_count; 226 227 if (node->flags & ANOBJ_EVALUATED) { 228 return; 229 } 230 231 if (!predefined) { 232 /* 233 * Not a predefined name. Check the incoming user argument count 234 * against the count that is specified in the method/object. 235 */ 236 if (node->type != ACPI_TYPE_METHOD) { 237 if (user_param_count) { 238 ACPI_INFO_PREDEFINED((AE_INFO, pathname, 239 ACPI_WARN_ALWAYS, 240 "%u arguments were passed to a non-method ACPI object (%s)", 241 user_param_count, 242 acpi_ut_get_type_name 243 (node->type))); 244 } 245 246 return; 247 } 248 249 /* 250 * This is a control method. Check the parameter count. 251 * We can only check the incoming argument count against the 252 * argument count declared for the method in the ASL/AML. 253 * 254 * Emit a message if too few or too many arguments have been passed 255 * by the caller. 256 * 257 * Note: Too many arguments will not cause the method to 258 * fail. However, the method will fail if there are too few 259 * arguments and the method attempts to use one of the missing ones. 260 */ 261 aml_param_count = node->object->method.param_count; 262 263 if (user_param_count < aml_param_count) { 264 ACPI_WARN_PREDEFINED((AE_INFO, pathname, 265 ACPI_WARN_ALWAYS, 266 "Insufficient arguments - " 267 "Caller passed %u, method requires %u", 268 user_param_count, 269 aml_param_count)); 270 } else if (user_param_count > aml_param_count) { 271 ACPI_INFO_PREDEFINED((AE_INFO, pathname, 272 ACPI_WARN_ALWAYS, 273 "Excess arguments - " 274 "Caller passed %u, method requires %u", 275 user_param_count, 276 aml_param_count)); 277 } 278 279 return; 280 } 281 282 /* 283 * This is a predefined name. Validate the user-supplied parameter 284 * count against the ACPI specification. We don't validate against 285 * the method itself because what is important here is that the 286 * caller is in conformance with the spec. (The arg count for the 287 * method was checked against the ACPI spec earlier.) 288 * 289 * Some methods are allowed to have a "minimum" number of args (_SCP) 290 * because their definition in ACPI has changed over time. 291 */ 292 required_param_count = 293 METHOD_GET_ARG_COUNT(predefined->info.argument_list); 294 295 if (user_param_count < required_param_count) { 296 ACPI_WARN_PREDEFINED((AE_INFO, pathname, ACPI_WARN_ALWAYS, 297 "Insufficient arguments - " 298 "Caller passed %u, ACPI requires %u", 299 user_param_count, required_param_count)); 300 } else if ((user_param_count > required_param_count) && 301 !(predefined->info.argument_list & ARG_COUNT_IS_MINIMUM)) { 302 ACPI_INFO_PREDEFINED((AE_INFO, pathname, ACPI_WARN_ALWAYS, 303 "Excess arguments - " 304 "Caller passed %u, ACPI requires %u", 305 user_param_count, required_param_count)); 306 } 307 } 308