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.h" 45 #include "accommon.h" 46 #include "acnamesp.h" 47 #include "acpredef.h" 48 49 50 #define _COMPONENT ACPI_NAMESPACE 51 ACPI_MODULE_NAME ("nsarguments") 52 53 54 /******************************************************************************* 55 * 56 * FUNCTION: AcpiNsCheckArgumentTypes 57 * 58 * PARAMETERS: Info - Method execution information block 59 * 60 * RETURN: None 61 * 62 * DESCRIPTION: Check the incoming argument count and all argument types 63 * against the argument type list for a predefined name. 64 * 65 ******************************************************************************/ 66 67 void 68 AcpiNsCheckArgumentTypes ( 69 ACPI_EVALUATE_INFO *Info) 70 { 71 UINT16 ArgTypeList; 72 UINT8 ArgCount; 73 UINT8 ArgType; 74 UINT8 UserArgType; 75 UINT32 i; 76 77 78 /* 79 * If not a predefined name, cannot typecheck args, because 80 * we have no idea what argument types are expected. 81 * Also, ignore typecheck if warnings/errors if this method 82 * has already been evaluated at least once -- in order 83 * to suppress repetitive messages. 84 */ 85 if (!Info->Predefined || (Info->Node->Flags & ANOBJ_EVALUATED)) 86 { 87 return; 88 } 89 90 ArgTypeList = Info->Predefined->Info.ArgumentList; 91 ArgCount = METHOD_GET_ARG_COUNT (ArgTypeList); 92 93 /* Typecheck all arguments */ 94 95 for (i = 0; ((i < ArgCount) && (i < Info->ParamCount)); i++) 96 { 97 ArgType = METHOD_GET_NEXT_TYPE (ArgTypeList); 98 UserArgType = Info->Parameters[i]->Common.Type; 99 100 if (UserArgType != ArgType) 101 { 102 ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, ACPI_WARN_ALWAYS, 103 "Argument #%u type mismatch - " 104 "Found [%s], ACPI requires [%s]", (i + 1), 105 AcpiUtGetTypeName (UserArgType), 106 AcpiUtGetTypeName (ArgType))); 107 108 /* Prevent any additional typechecking for this method */ 109 110 Info->Node->Flags |= ANOBJ_EVALUATED; 111 } 112 } 113 } 114 115 116 /******************************************************************************* 117 * 118 * FUNCTION: AcpiNsCheckAcpiCompliance 119 * 120 * PARAMETERS: Pathname - Full pathname to the node (for error msgs) 121 * Node - Namespace node for the method/object 122 * Predefined - Pointer to entry in predefined name table 123 * 124 * RETURN: None 125 * 126 * DESCRIPTION: Check that the declared parameter count (in ASL/AML) for a 127 * predefined name is what is expected (matches what is defined in 128 * the ACPI specification for this predefined name.) 129 * 130 ******************************************************************************/ 131 132 void 133 AcpiNsCheckAcpiCompliance ( 134 char *Pathname, 135 ACPI_NAMESPACE_NODE *Node, 136 const ACPI_PREDEFINED_INFO *Predefined) 137 { 138 UINT32 AmlParamCount; 139 UINT32 RequiredParamCount; 140 141 142 if (!Predefined || (Node->Flags & ANOBJ_EVALUATED)) 143 { 144 return; 145 } 146 147 /* Get the ACPI-required arg count from the predefined info table */ 148 149 RequiredParamCount = 150 METHOD_GET_ARG_COUNT (Predefined->Info.ArgumentList); 151 152 /* 153 * If this object is not a control method, we can check if the ACPI 154 * spec requires that it be a method. 155 */ 156 if (Node->Type != ACPI_TYPE_METHOD) 157 { 158 if (RequiredParamCount > 0) 159 { 160 /* Object requires args, must be implemented as a method */ 161 162 ACPI_BIOS_ERROR_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 163 "Object (%s) must be a control method with %u arguments", 164 AcpiUtGetTypeName (Node->Type), RequiredParamCount)); 165 } 166 else if (!RequiredParamCount && !Predefined->Info.ExpectedBtypes) 167 { 168 /* Object requires no args and no return value, must be a method */ 169 170 ACPI_BIOS_ERROR_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 171 "Object (%s) must be a control method " 172 "with no arguments and no return value", 173 AcpiUtGetTypeName (Node->Type))); 174 } 175 176 return; 177 } 178 179 /* 180 * This is a control method. 181 * Check that the ASL/AML-defined parameter count for this method 182 * matches the ACPI-required parameter count 183 * 184 * Some methods are allowed to have a "minimum" number of args (_SCP) 185 * because their definition in ACPI has changed over time. 186 * 187 * Note: These are BIOS errors in the declaration of the object 188 */ 189 AmlParamCount = Node->Object->Method.ParamCount; 190 191 if (AmlParamCount < RequiredParamCount) 192 { 193 ACPI_BIOS_ERROR_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 194 "Insufficient arguments - " 195 "ASL declared %u, ACPI requires %u", 196 AmlParamCount, RequiredParamCount)); 197 } 198 else if ((AmlParamCount > RequiredParamCount) && 199 !(Predefined->Info.ArgumentList & ARG_COUNT_IS_MINIMUM)) 200 { 201 ACPI_BIOS_ERROR_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 202 "Excess arguments - " 203 "ASL declared %u, ACPI requires %u", 204 AmlParamCount, RequiredParamCount)); 205 } 206 } 207 208 209 /******************************************************************************* 210 * 211 * FUNCTION: AcpiNsCheckArgumentCount 212 * 213 * PARAMETERS: Pathname - Full pathname to the node (for error msgs) 214 * Node - Namespace node for the method/object 215 * UserParamCount - Number of args passed in by the caller 216 * Predefined - Pointer to entry in predefined name table 217 * 218 * RETURN: None 219 * 220 * DESCRIPTION: Check that incoming argument count matches the declared 221 * parameter count (in the ASL/AML) for an object. 222 * 223 ******************************************************************************/ 224 225 void 226 AcpiNsCheckArgumentCount ( 227 char *Pathname, 228 ACPI_NAMESPACE_NODE *Node, 229 UINT32 UserParamCount, 230 const ACPI_PREDEFINED_INFO *Predefined) 231 { 232 UINT32 AmlParamCount; 233 UINT32 RequiredParamCount; 234 235 236 if (Node->Flags & ANOBJ_EVALUATED) 237 { 238 return; 239 } 240 241 if (!Predefined) 242 { 243 /* 244 * Not a predefined name. Check the incoming user argument count 245 * against the count that is specified in the method/object. 246 */ 247 if (Node->Type != ACPI_TYPE_METHOD) 248 { 249 if (UserParamCount) 250 { 251 ACPI_INFO_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 252 "%u arguments were passed to a non-method ACPI object (%s)", 253 UserParamCount, AcpiUtGetTypeName (Node->Type))); 254 } 255 256 return; 257 } 258 259 /* 260 * This is a control method. Check the parameter count. 261 * We can only check the incoming argument count against the 262 * argument count declared for the method in the ASL/AML. 263 * 264 * Emit a message if too few or too many arguments have been passed 265 * by the caller. 266 * 267 * Note: Too many arguments will not cause the method to 268 * fail. However, the method will fail if there are too few 269 * arguments and the method attempts to use one of the missing ones. 270 */ 271 AmlParamCount = Node->Object->Method.ParamCount; 272 273 if (UserParamCount < AmlParamCount) 274 { 275 ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 276 "Insufficient arguments - " 277 "Caller passed %u, method requires %u", 278 UserParamCount, AmlParamCount)); 279 } 280 else if (UserParamCount > AmlParamCount) 281 { 282 ACPI_INFO_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 283 "Excess arguments - " 284 "Caller passed %u, method requires %u", 285 UserParamCount, AmlParamCount)); 286 } 287 288 return; 289 } 290 291 /* 292 * This is a predefined name. Validate the user-supplied parameter 293 * count against the ACPI specification. We don't validate against 294 * the method itself because what is important here is that the 295 * caller is in conformance with the spec. (The arg count for the 296 * method was checked against the ACPI spec earlier.) 297 * 298 * Some methods are allowed to have a "minimum" number of args (_SCP) 299 * because their definition in ACPI has changed over time. 300 */ 301 RequiredParamCount = 302 METHOD_GET_ARG_COUNT (Predefined->Info.ArgumentList); 303 304 if (UserParamCount < RequiredParamCount) 305 { 306 ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 307 "Insufficient arguments - " 308 "Caller passed %u, ACPI requires %u", 309 UserParamCount, RequiredParamCount)); 310 } 311 else if ((UserParamCount > RequiredParamCount) && 312 !(Predefined->Info.ArgumentList & ARG_COUNT_IS_MINIMUM)) 313 { 314 ACPI_INFO_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 315 "Excess arguments - " 316 "Caller passed %u, ACPI requires %u", 317 UserParamCount, RequiredParamCount)); 318 } 319 } 320