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