1 /****************************************************************************** 2 * 3 * Module Name: nsarguments - Validation of args for ACPI predefined methods 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2020, 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 /* No typechecking for ACPI_TYPE_ANY */ 101 102 if ((UserArgType != ArgType) && (ArgType != ACPI_TYPE_ANY)) 103 { 104 ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, ACPI_WARN_ALWAYS, 105 "Argument #%u type mismatch - " 106 "Found [%s], ACPI requires [%s]", (i + 1), 107 AcpiUtGetTypeName (UserArgType), 108 AcpiUtGetTypeName (ArgType))); 109 110 /* Prevent any additional typechecking for this method */ 111 112 Info->Node->Flags |= ANOBJ_EVALUATED; 113 } 114 } 115 } 116 117 118 /******************************************************************************* 119 * 120 * FUNCTION: AcpiNsCheckAcpiCompliance 121 * 122 * PARAMETERS: Pathname - Full pathname to the node (for error msgs) 123 * Node - Namespace node for the method/object 124 * Predefined - Pointer to entry in predefined name table 125 * 126 * RETURN: None 127 * 128 * DESCRIPTION: Check that the declared parameter count (in ASL/AML) for a 129 * predefined name is what is expected (matches what is defined in 130 * the ACPI specification for this predefined name.) 131 * 132 ******************************************************************************/ 133 134 void 135 AcpiNsCheckAcpiCompliance ( 136 char *Pathname, 137 ACPI_NAMESPACE_NODE *Node, 138 const ACPI_PREDEFINED_INFO *Predefined) 139 { 140 UINT32 AmlParamCount; 141 UINT32 RequiredParamCount; 142 143 144 if (!Predefined || (Node->Flags & ANOBJ_EVALUATED)) 145 { 146 return; 147 } 148 149 /* Get the ACPI-required arg count from the predefined info table */ 150 151 RequiredParamCount = 152 METHOD_GET_ARG_COUNT (Predefined->Info.ArgumentList); 153 154 /* 155 * If this object is not a control method, we can check if the ACPI 156 * spec requires that it be a method. 157 */ 158 if (Node->Type != ACPI_TYPE_METHOD) 159 { 160 if (RequiredParamCount > 0) 161 { 162 /* Object requires args, must be implemented as a method */ 163 164 ACPI_BIOS_ERROR_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 165 "Object (%s) must be a control method with %u arguments", 166 AcpiUtGetTypeName (Node->Type), RequiredParamCount)); 167 } 168 else if (!RequiredParamCount && !Predefined->Info.ExpectedBtypes) 169 { 170 /* Object requires no args and no return value, must be a method */ 171 172 ACPI_BIOS_ERROR_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 173 "Object (%s) must be a control method " 174 "with no arguments and no return value", 175 AcpiUtGetTypeName (Node->Type))); 176 } 177 178 return; 179 } 180 181 /* 182 * This is a control method. 183 * Check that the ASL/AML-defined parameter count for this method 184 * matches the ACPI-required parameter count 185 * 186 * Some methods are allowed to have a "minimum" number of args (_SCP) 187 * because their definition in ACPI has changed over time. 188 * 189 * Note: These are BIOS errors in the declaration of the object 190 */ 191 AmlParamCount = Node->Object->Method.ParamCount; 192 193 if (AmlParamCount < RequiredParamCount) 194 { 195 ACPI_BIOS_ERROR_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 196 "Insufficient arguments - " 197 "ASL declared %u, ACPI requires %u", 198 AmlParamCount, RequiredParamCount)); 199 } 200 else if ((AmlParamCount > RequiredParamCount) && 201 !(Predefined->Info.ArgumentList & ARG_COUNT_IS_MINIMUM)) 202 { 203 ACPI_BIOS_ERROR_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 204 "Excess arguments - " 205 "ASL declared %u, ACPI requires %u", 206 AmlParamCount, RequiredParamCount)); 207 } 208 } 209 210 211 /******************************************************************************* 212 * 213 * FUNCTION: AcpiNsCheckArgumentCount 214 * 215 * PARAMETERS: Pathname - Full pathname to the node (for error msgs) 216 * Node - Namespace node for the method/object 217 * UserParamCount - Number of args passed in by the caller 218 * Predefined - Pointer to entry in predefined name table 219 * 220 * RETURN: None 221 * 222 * DESCRIPTION: Check that incoming argument count matches the declared 223 * parameter count (in the ASL/AML) for an object. 224 * 225 ******************************************************************************/ 226 227 void 228 AcpiNsCheckArgumentCount ( 229 char *Pathname, 230 ACPI_NAMESPACE_NODE *Node, 231 UINT32 UserParamCount, 232 const ACPI_PREDEFINED_INFO *Predefined) 233 { 234 UINT32 AmlParamCount; 235 UINT32 RequiredParamCount; 236 237 238 if (Node->Flags & ANOBJ_EVALUATED) 239 { 240 return; 241 } 242 243 if (!Predefined) 244 { 245 /* 246 * Not a predefined name. Check the incoming user argument count 247 * against the count that is specified in the method/object. 248 */ 249 if (Node->Type != ACPI_TYPE_METHOD) 250 { 251 if (UserParamCount) 252 { 253 ACPI_INFO_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 254 "%u arguments were passed to a non-method ACPI object (%s)", 255 UserParamCount, AcpiUtGetTypeName (Node->Type))); 256 } 257 258 return; 259 } 260 261 /* 262 * This is a control method. Check the parameter count. 263 * We can only check the incoming argument count against the 264 * argument count declared for the method in the ASL/AML. 265 * 266 * Emit a message if too few or too many arguments have been passed 267 * by the caller. 268 * 269 * Note: Too many arguments will not cause the method to 270 * fail. However, the method will fail if there are too few 271 * arguments and the method attempts to use one of the missing ones. 272 */ 273 AmlParamCount = Node->Object->Method.ParamCount; 274 275 if (UserParamCount < AmlParamCount) 276 { 277 ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 278 "Insufficient arguments - " 279 "Caller passed %u, method requires %u", 280 UserParamCount, AmlParamCount)); 281 } 282 else if (UserParamCount > AmlParamCount) 283 { 284 ACPI_INFO_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 285 "Excess arguments - " 286 "Caller passed %u, method requires %u", 287 UserParamCount, AmlParamCount)); 288 } 289 290 return; 291 } 292 293 /* 294 * This is a predefined name. Validate the user-supplied parameter 295 * count against the ACPI specification. We don't validate against 296 * the method itself because what is important here is that the 297 * caller is in conformance with the spec. (The arg count for the 298 * method was checked against the ACPI spec earlier.) 299 * 300 * Some methods are allowed to have a "minimum" number of args (_SCP) 301 * because their definition in ACPI has changed over time. 302 */ 303 RequiredParamCount = 304 METHOD_GET_ARG_COUNT (Predefined->Info.ArgumentList); 305 306 if (UserParamCount < RequiredParamCount) 307 { 308 ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 309 "Insufficient arguments - " 310 "Caller passed %u, ACPI requires %u", 311 UserParamCount, RequiredParamCount)); 312 } 313 else if ((UserParamCount > RequiredParamCount) && 314 !(Predefined->Info.ArgumentList & ARG_COUNT_IS_MINIMUM)) 315 { 316 ACPI_INFO_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 317 "Excess arguments - " 318 "Caller passed %u, ACPI requires %u", 319 UserParamCount, RequiredParamCount)); 320 } 321 } 322