1 /****************************************************************************** 2 * 3 * Module Name: nsarguments - Validation of args for ACPI predefined methods 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2016, 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 /* If not a predefined name, cannot typecheck args */ 73 74 if (!info->predefined) { 75 return; 76 } 77 78 arg_type_list = info->predefined->info.argument_list; 79 arg_count = METHOD_GET_ARG_COUNT(arg_type_list); 80 81 /* Typecheck all arguments */ 82 83 for (i = 0; ((i < arg_count) && (i < info->param_count)); i++) { 84 arg_type = METHOD_GET_NEXT_TYPE(arg_type_list); 85 user_arg_type = info->parameters[i]->common.type; 86 87 if (user_arg_type != arg_type) { 88 ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, 89 ACPI_WARN_ALWAYS, 90 "Argument #%u type mismatch - " 91 "Found [%s], ACPI requires [%s]", 92 (i + 1), 93 acpi_ut_get_type_name 94 (user_arg_type), 95 acpi_ut_get_type_name(arg_type))); 96 } 97 } 98 } 99 100 /******************************************************************************* 101 * 102 * FUNCTION: acpi_ns_check_acpi_compliance 103 * 104 * PARAMETERS: pathname - Full pathname to the node (for error msgs) 105 * node - Namespace node for the method/object 106 * predefined - Pointer to entry in predefined name table 107 * 108 * RETURN: None 109 * 110 * DESCRIPTION: Check that the declared parameter count (in ASL/AML) for a 111 * predefined name is what is expected (matches what is defined in 112 * the ACPI specification for this predefined name.) 113 * 114 ******************************************************************************/ 115 116 void 117 acpi_ns_check_acpi_compliance(char *pathname, 118 struct acpi_namespace_node *node, 119 const union acpi_predefined_info *predefined) 120 { 121 u32 aml_param_count; 122 u32 required_param_count; 123 124 if (!predefined) { 125 return; 126 } 127 128 /* Get the ACPI-required arg count from the predefined info table */ 129 130 required_param_count = 131 METHOD_GET_ARG_COUNT(predefined->info.argument_list); 132 133 /* 134 * If this object is not a control method, we can check if the ACPI 135 * spec requires that it be a method. 136 */ 137 if (node->type != ACPI_TYPE_METHOD) { 138 if (required_param_count > 0) { 139 140 /* Object requires args, must be implemented as a method */ 141 142 ACPI_BIOS_ERROR_PREDEFINED((AE_INFO, pathname, 143 ACPI_WARN_ALWAYS, 144 "Object (%s) must be a control method with %u arguments", 145 acpi_ut_get_type_name(node-> 146 type), 147 required_param_count)); 148 } else if (!required_param_count 149 && !predefined->info.expected_btypes) { 150 151 /* Object requires no args and no return value, must be a method */ 152 153 ACPI_BIOS_ERROR_PREDEFINED((AE_INFO, pathname, 154 ACPI_WARN_ALWAYS, 155 "Object (%s) must be a control method " 156 "with no arguments and no return value", 157 acpi_ut_get_type_name(node-> 158 type))); 159 } 160 161 return; 162 } 163 164 /* 165 * This is a control method. 166 * Check that the ASL/AML-defined parameter count for this method 167 * matches the ACPI-required parameter count 168 * 169 * Some methods are allowed to have a "minimum" number of args (_SCP) 170 * because their definition in ACPI has changed over time. 171 * 172 * Note: These are BIOS errors in the declaration of the object 173 */ 174 aml_param_count = node->object->method.param_count; 175 176 if (aml_param_count < required_param_count) { 177 ACPI_BIOS_ERROR_PREDEFINED((AE_INFO, pathname, ACPI_WARN_ALWAYS, 178 "Insufficient arguments - " 179 "ASL declared %u, ACPI requires %u", 180 aml_param_count, 181 required_param_count)); 182 } else if ((aml_param_count > required_param_count) 183 && !(predefined->info. 184 argument_list & ARG_COUNT_IS_MINIMUM)) { 185 ACPI_BIOS_ERROR_PREDEFINED((AE_INFO, pathname, ACPI_WARN_ALWAYS, 186 "Excess arguments - " 187 "ASL declared %u, ACPI requires %u", 188 aml_param_count, 189 required_param_count)); 190 } 191 } 192 193 /******************************************************************************* 194 * 195 * FUNCTION: acpi_ns_check_argument_count 196 * 197 * PARAMETERS: pathname - Full pathname to the node (for error msgs) 198 * node - Namespace node for the method/object 199 * user_param_count - Number of args passed in by the caller 200 * predefined - Pointer to entry in predefined name table 201 * 202 * RETURN: None 203 * 204 * DESCRIPTION: Check that incoming argument count matches the declared 205 * parameter count (in the ASL/AML) for an object. 206 * 207 ******************************************************************************/ 208 209 void 210 acpi_ns_check_argument_count(char *pathname, 211 struct acpi_namespace_node *node, 212 u32 user_param_count, 213 const union acpi_predefined_info *predefined) 214 { 215 u32 aml_param_count; 216 u32 required_param_count; 217 218 if (!predefined) { 219 /* 220 * Not a predefined name. Check the incoming user argument count 221 * against the count that is specified in the method/object. 222 */ 223 if (node->type != ACPI_TYPE_METHOD) { 224 if (user_param_count) { 225 ACPI_INFO_PREDEFINED((AE_INFO, pathname, 226 ACPI_WARN_ALWAYS, 227 "%u arguments were passed to a non-method ACPI object (%s)", 228 user_param_count, 229 acpi_ut_get_type_name 230 (node->type))); 231 } 232 233 return; 234 } 235 236 /* 237 * This is a control method. Check the parameter count. 238 * We can only check the incoming argument count against the 239 * argument count declared for the method in the ASL/AML. 240 * 241 * Emit a message if too few or too many arguments have been passed 242 * by the caller. 243 * 244 * Note: Too many arguments will not cause the method to 245 * fail. However, the method will fail if there are too few 246 * arguments and the method attempts to use one of the missing ones. 247 */ 248 aml_param_count = node->object->method.param_count; 249 250 if (user_param_count < aml_param_count) { 251 ACPI_WARN_PREDEFINED((AE_INFO, pathname, 252 ACPI_WARN_ALWAYS, 253 "Insufficient arguments - " 254 "Caller passed %u, method requires %u", 255 user_param_count, 256 aml_param_count)); 257 } else if (user_param_count > aml_param_count) { 258 ACPI_INFO_PREDEFINED((AE_INFO, pathname, 259 ACPI_WARN_ALWAYS, 260 "Excess arguments - " 261 "Caller passed %u, method requires %u", 262 user_param_count, 263 aml_param_count)); 264 } 265 266 return; 267 } 268 269 /* 270 * This is a predefined name. Validate the user-supplied parameter 271 * count against the ACPI specification. We don't validate against 272 * the method itself because what is important here is that the 273 * caller is in conformance with the spec. (The arg count for the 274 * method was checked against the ACPI spec earlier.) 275 * 276 * Some methods are allowed to have a "minimum" number of args (_SCP) 277 * because their definition in ACPI has changed over time. 278 */ 279 required_param_count = 280 METHOD_GET_ARG_COUNT(predefined->info.argument_list); 281 282 if (user_param_count < required_param_count) { 283 ACPI_WARN_PREDEFINED((AE_INFO, pathname, ACPI_WARN_ALWAYS, 284 "Insufficient arguments - " 285 "Caller passed %u, ACPI requires %u", 286 user_param_count, required_param_count)); 287 } else if ((user_param_count > required_param_count) && 288 !(predefined->info.argument_list & ARG_COUNT_IS_MINIMUM)) { 289 ACPI_INFO_PREDEFINED((AE_INFO, pathname, ACPI_WARN_ALWAYS, 290 "Excess arguments - " 291 "Caller passed %u, ACPI requires %u", 292 user_param_count, required_param_count)); 293 } 294 } 295