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 <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 = 141 METHOD_GET_ARG_COUNT (Predefined->Info.ArgumentList); 142 143 /* 144 * If this object is not a control method, we can check if the ACPI 145 * spec requires that it be a method. 146 */ 147 if (Node->Type != ACPI_TYPE_METHOD) 148 { 149 if (RequiredParamCount > 0) 150 { 151 /* Object requires args, must be implemented as a method */ 152 153 ACPI_BIOS_ERROR_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 154 "Object (%s) must be a control method with %u arguments", 155 AcpiUtGetTypeName (Node->Type), RequiredParamCount)); 156 } 157 else if (!RequiredParamCount && !Predefined->Info.ExpectedBtypes) 158 { 159 /* Object requires no args and no return value, must be a method */ 160 161 ACPI_BIOS_ERROR_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 162 "Object (%s) must be a control method " 163 "with no arguments and no return value", 164 AcpiUtGetTypeName (Node->Type))); 165 } 166 167 return; 168 } 169 170 /* 171 * This is a control method. 172 * Check that the ASL/AML-defined parameter count for this method 173 * matches the ACPI-required parameter count 174 * 175 * Some methods are allowed to have a "minimum" number of args (_SCP) 176 * because their definition in ACPI has changed over time. 177 * 178 * Note: These are BIOS errors in the declaration of the object 179 */ 180 AmlParamCount = Node->Object->Method.ParamCount; 181 182 if (AmlParamCount < RequiredParamCount) 183 { 184 ACPI_BIOS_ERROR_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 185 "Insufficient arguments - " 186 "ASL declared %u, ACPI requires %u", 187 AmlParamCount, RequiredParamCount)); 188 } 189 else if ((AmlParamCount > RequiredParamCount) && 190 !(Predefined->Info.ArgumentList & ARG_COUNT_IS_MINIMUM)) 191 { 192 ACPI_BIOS_ERROR_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 193 "Excess arguments - " 194 "ASL declared %u, ACPI requires %u", 195 AmlParamCount, RequiredParamCount)); 196 } 197 } 198 199 200 /******************************************************************************* 201 * 202 * FUNCTION: AcpiNsCheckArgumentCount 203 * 204 * PARAMETERS: Pathname - Full pathname to the node (for error msgs) 205 * Node - Namespace node for the method/object 206 * UserParamCount - Number of args passed in by the caller 207 * Predefined - Pointer to entry in predefined name table 208 * 209 * RETURN: None 210 * 211 * DESCRIPTION: Check that incoming argument count matches the declared 212 * parameter count (in the ASL/AML) for an object. 213 * 214 ******************************************************************************/ 215 216 void 217 AcpiNsCheckArgumentCount ( 218 char *Pathname, 219 ACPI_NAMESPACE_NODE *Node, 220 UINT32 UserParamCount, 221 const ACPI_PREDEFINED_INFO *Predefined) 222 { 223 UINT32 AmlParamCount; 224 UINT32 RequiredParamCount; 225 226 227 if (!Predefined) 228 { 229 /* 230 * Not a predefined name. Check the incoming user argument count 231 * against the count that is specified in the method/object. 232 */ 233 if (Node->Type != ACPI_TYPE_METHOD) 234 { 235 if (UserParamCount) 236 { 237 ACPI_INFO_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 238 "%u arguments were passed to a non-method ACPI object (%s)", 239 UserParamCount, AcpiUtGetTypeName (Node->Type))); 240 } 241 242 return; 243 } 244 245 /* 246 * This is a control method. Check the parameter count. 247 * We can only check the incoming argument count against the 248 * argument count declared for the method in the ASL/AML. 249 * 250 * Emit a message if too few or too many arguments have been passed 251 * by the caller. 252 * 253 * Note: Too many arguments will not cause the method to 254 * fail. However, the method will fail if there are too few 255 * arguments and the method attempts to use one of the missing ones. 256 */ 257 AmlParamCount = Node->Object->Method.ParamCount; 258 259 if (UserParamCount < AmlParamCount) 260 { 261 ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 262 "Insufficient arguments - " 263 "Caller passed %u, method requires %u", 264 UserParamCount, AmlParamCount)); 265 } 266 else if (UserParamCount > AmlParamCount) 267 { 268 ACPI_INFO_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 269 "Excess arguments - " 270 "Caller passed %u, method requires %u", 271 UserParamCount, AmlParamCount)); 272 } 273 274 return; 275 } 276 277 /* 278 * This is a predefined name. Validate the user-supplied parameter 279 * count against the ACPI specification. We don't validate against 280 * the method itself because what is important here is that the 281 * caller is in conformance with the spec. (The arg count for the 282 * method was checked against the ACPI spec earlier.) 283 * 284 * Some methods are allowed to have a "minimum" number of args (_SCP) 285 * because their definition in ACPI has changed over time. 286 */ 287 RequiredParamCount = 288 METHOD_GET_ARG_COUNT (Predefined->Info.ArgumentList); 289 290 if (UserParamCount < RequiredParamCount) 291 { 292 ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 293 "Insufficient arguments - " 294 "Caller passed %u, ACPI requires %u", 295 UserParamCount, RequiredParamCount)); 296 } 297 else if ((UserParamCount > RequiredParamCount) && 298 !(Predefined->Info.ArgumentList & ARG_COUNT_IS_MINIMUM)) 299 { 300 ACPI_INFO_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, 301 "Excess arguments - " 302 "Caller passed %u, ACPI requires %u", 303 UserParamCount, RequiredParamCount)); 304 } 305 } 306