1 2 /****************************************************************************** 3 * 4 * Module Name: exoparg6 - AML execution - opcodes with 6 arguments 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2011, Intel Corp. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * substantially similar to the "NO WARRANTY" disclaimer below 20 * ("Disclaimer") and any redistribution must be conditioned upon 21 * including a substantially similar Disclaimer requirement for further 22 * binary redistribution. 23 * 3. Neither the names of the above-listed copyright holders nor the names 24 * of any contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * Alternatively, this software may be distributed under the terms of the 28 * GNU General Public License ("GPL") version 2 as published by the Free 29 * Software Foundation. 30 * 31 * NO WARRANTY 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGES. 43 */ 44 45 #define __EXOPARG6_C__ 46 47 #include "acpi.h" 48 #include "accommon.h" 49 #include "acinterp.h" 50 #include "acparser.h" 51 #include "amlcode.h" 52 53 54 #define _COMPONENT ACPI_EXECUTER 55 ACPI_MODULE_NAME ("exoparg6") 56 57 58 /*! 59 * Naming convention for AML interpreter execution routines. 60 * 61 * The routines that begin execution of AML opcodes are named with a common 62 * convention based upon the number of arguments, the number of target operands, 63 * and whether or not a value is returned: 64 * 65 * AcpiExOpcode_xA_yT_zR 66 * 67 * Where: 68 * 69 * xA - ARGUMENTS: The number of arguments (input operands) that are 70 * required for this opcode type (1 through 6 args). 71 * yT - TARGETS: The number of targets (output operands) that are required 72 * for this opcode type (0, 1, or 2 targets). 73 * zR - RETURN VALUE: Indicates whether this opcode type returns a value 74 * as the function return (0 or 1). 75 * 76 * The AcpiExOpcode* functions are called via the Dispatcher component with 77 * fully resolved operands. 78 !*/ 79 80 /* Local prototypes */ 81 82 static BOOLEAN 83 AcpiExDoMatch ( 84 UINT32 MatchOp, 85 ACPI_OPERAND_OBJECT *PackageObj, 86 ACPI_OPERAND_OBJECT *MatchObj); 87 88 89 /******************************************************************************* 90 * 91 * FUNCTION: AcpiExDoMatch 92 * 93 * PARAMETERS: MatchOp - The AML match operand 94 * PackageObj - Object from the target package 95 * MatchObj - Object to be matched 96 * 97 * RETURN: TRUE if the match is successful, FALSE otherwise 98 * 99 * DESCRIPTION: Implements the low-level match for the ASL Match operator. 100 * Package elements will be implicitly converted to the type of 101 * the match object (Integer/Buffer/String). 102 * 103 ******************************************************************************/ 104 105 static BOOLEAN 106 AcpiExDoMatch ( 107 UINT32 MatchOp, 108 ACPI_OPERAND_OBJECT *PackageObj, 109 ACPI_OPERAND_OBJECT *MatchObj) 110 { 111 BOOLEAN LogicalResult = TRUE; 112 ACPI_STATUS Status; 113 114 115 /* 116 * Note: Since the PackageObj/MatchObj ordering is opposite to that of 117 * the standard logical operators, we have to reverse them when we call 118 * DoLogicalOp in order to make the implicit conversion rules work 119 * correctly. However, this means we have to flip the entire equation 120 * also. A bit ugly perhaps, but overall, better than fussing the 121 * parameters around at runtime, over and over again. 122 * 123 * Below, P[i] refers to the package element, M refers to the Match object. 124 */ 125 switch (MatchOp) 126 { 127 case MATCH_MTR: 128 129 /* Always true */ 130 131 break; 132 133 case MATCH_MEQ: 134 135 /* 136 * True if equal: (P[i] == M) 137 * Change to: (M == P[i]) 138 */ 139 Status = AcpiExDoLogicalOp (AML_LEQUAL_OP, MatchObj, PackageObj, 140 &LogicalResult); 141 if (ACPI_FAILURE (Status)) 142 { 143 return (FALSE); 144 } 145 break; 146 147 case MATCH_MLE: 148 149 /* 150 * True if less than or equal: (P[i] <= M) (P[i] NotGreater than M) 151 * Change to: (M >= P[i]) (M NotLess than P[i]) 152 */ 153 Status = AcpiExDoLogicalOp (AML_LLESS_OP, MatchObj, PackageObj, 154 &LogicalResult); 155 if (ACPI_FAILURE (Status)) 156 { 157 return (FALSE); 158 } 159 LogicalResult = (BOOLEAN) !LogicalResult; 160 break; 161 162 case MATCH_MLT: 163 164 /* 165 * True if less than: (P[i] < M) 166 * Change to: (M > P[i]) 167 */ 168 Status = AcpiExDoLogicalOp (AML_LGREATER_OP, MatchObj, PackageObj, 169 &LogicalResult); 170 if (ACPI_FAILURE (Status)) 171 { 172 return (FALSE); 173 } 174 break; 175 176 case MATCH_MGE: 177 178 /* 179 * True if greater than or equal: (P[i] >= M) (P[i] NotLess than M) 180 * Change to: (M <= P[i]) (M NotGreater than P[i]) 181 */ 182 Status = AcpiExDoLogicalOp (AML_LGREATER_OP, MatchObj, PackageObj, 183 &LogicalResult); 184 if (ACPI_FAILURE (Status)) 185 { 186 return (FALSE); 187 } 188 LogicalResult = (BOOLEAN)!LogicalResult; 189 break; 190 191 case MATCH_MGT: 192 193 /* 194 * True if greater than: (P[i] > M) 195 * Change to: (M < P[i]) 196 */ 197 Status = AcpiExDoLogicalOp (AML_LLESS_OP, MatchObj, PackageObj, 198 &LogicalResult); 199 if (ACPI_FAILURE (Status)) 200 { 201 return (FALSE); 202 } 203 break; 204 205 default: 206 207 /* Undefined */ 208 209 return (FALSE); 210 } 211 212 return LogicalResult; 213 } 214 215 216 /******************************************************************************* 217 * 218 * FUNCTION: AcpiExOpcode_6A_0T_1R 219 * 220 * PARAMETERS: WalkState - Current walk state 221 * 222 * RETURN: Status 223 * 224 * DESCRIPTION: Execute opcode with 6 arguments, no target, and a return value 225 * 226 ******************************************************************************/ 227 228 ACPI_STATUS 229 AcpiExOpcode_6A_0T_1R ( 230 ACPI_WALK_STATE *WalkState) 231 { 232 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 233 ACPI_OPERAND_OBJECT *ReturnDesc = NULL; 234 ACPI_STATUS Status = AE_OK; 235 UINT64 Index; 236 ACPI_OPERAND_OBJECT *ThisElement; 237 238 239 ACPI_FUNCTION_TRACE_STR (ExOpcode_6A_0T_1R, 240 AcpiPsGetOpcodeName (WalkState->Opcode)); 241 242 243 switch (WalkState->Opcode) 244 { 245 case AML_MATCH_OP: 246 /* 247 * Match (SearchPkg[0], MatchOp1[1], MatchObj1[2], 248 * MatchOp2[3], MatchObj2[4], StartIndex[5]) 249 */ 250 251 /* Validate both Match Term Operators (MTR, MEQ, etc.) */ 252 253 if ((Operand[1]->Integer.Value > MAX_MATCH_OPERATOR) || 254 (Operand[3]->Integer.Value > MAX_MATCH_OPERATOR)) 255 { 256 ACPI_ERROR ((AE_INFO, "Match operator out of range")); 257 Status = AE_AML_OPERAND_VALUE; 258 goto Cleanup; 259 } 260 261 /* Get the package StartIndex, validate against the package length */ 262 263 Index = Operand[5]->Integer.Value; 264 if (Index >= Operand[0]->Package.Count) 265 { 266 ACPI_ERROR ((AE_INFO, 267 "Index (0x%8.8X%8.8X) beyond package end (0x%X)", 268 ACPI_FORMAT_UINT64 (Index), Operand[0]->Package.Count)); 269 Status = AE_AML_PACKAGE_LIMIT; 270 goto Cleanup; 271 } 272 273 /* Create an integer for the return value */ 274 /* Default return value is ACPI_UINT64_MAX if no match found */ 275 276 ReturnDesc = AcpiUtCreateIntegerObject (ACPI_UINT64_MAX); 277 if (!ReturnDesc) 278 { 279 Status = AE_NO_MEMORY; 280 goto Cleanup; 281 282 } 283 284 /* 285 * Examine each element until a match is found. Both match conditions 286 * must be satisfied for a match to occur. Within the loop, 287 * "continue" signifies that the current element does not match 288 * and the next should be examined. 289 * 290 * Upon finding a match, the loop will terminate via "break" at 291 * the bottom. If it terminates "normally", MatchValue will be 292 * ACPI_UINT64_MAX (Ones) (its initial value) indicating that no 293 * match was found. 294 */ 295 for ( ; Index < Operand[0]->Package.Count; Index++) 296 { 297 /* Get the current package element */ 298 299 ThisElement = Operand[0]->Package.Elements[Index]; 300 301 /* Treat any uninitialized (NULL) elements as non-matching */ 302 303 if (!ThisElement) 304 { 305 continue; 306 } 307 308 /* 309 * Both match conditions must be satisfied. Execution of a continue 310 * (proceed to next iteration of enclosing for loop) signifies a 311 * non-match. 312 */ 313 if (!AcpiExDoMatch ((UINT32) Operand[1]->Integer.Value, 314 ThisElement, Operand[2])) 315 { 316 continue; 317 } 318 319 if (!AcpiExDoMatch ((UINT32) Operand[3]->Integer.Value, 320 ThisElement, Operand[4])) 321 { 322 continue; 323 } 324 325 /* Match found: Index is the return value */ 326 327 ReturnDesc->Integer.Value = Index; 328 break; 329 } 330 break; 331 332 333 case AML_LOAD_TABLE_OP: 334 335 Status = AcpiExLoadTableOp (WalkState, &ReturnDesc); 336 break; 337 338 339 default: 340 341 ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", 342 WalkState->Opcode)); 343 Status = AE_AML_BAD_OPCODE; 344 goto Cleanup; 345 } 346 347 348 Cleanup: 349 350 /* Delete return object on error */ 351 352 if (ACPI_FAILURE (Status)) 353 { 354 AcpiUtRemoveReference (ReturnDesc); 355 } 356 357 /* Save return object on success */ 358 359 else 360 { 361 WalkState->ResultObj = ReturnDesc; 362 } 363 364 return_ACPI_STATUS (Status); 365 } 366