1 /****************************************************************************** 2 * 3 * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes 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 <acpi/acpi.h> 45 #include "accommon.h" 46 #include "acinterp.h" 47 #include "amlcode.h" 48 49 #define _COMPONENT ACPI_EXECUTER 50 ACPI_MODULE_NAME("exmisc") 51 52 /******************************************************************************* 53 * 54 * FUNCTION: acpi_ex_get_object_reference 55 * 56 * PARAMETERS: obj_desc - Create a reference to this object 57 * return_desc - Where to store the reference 58 * walk_state - Current state 59 * 60 * RETURN: Status 61 * 62 * DESCRIPTION: Obtain and return a "reference" to the target object 63 * Common code for the ref_of_op and the cond_ref_of_op. 64 * 65 ******************************************************************************/ 66 acpi_status 67 acpi_ex_get_object_reference(union acpi_operand_object *obj_desc, 68 union acpi_operand_object **return_desc, 69 struct acpi_walk_state *walk_state) 70 { 71 union acpi_operand_object *reference_obj; 72 union acpi_operand_object *referenced_obj; 73 74 ACPI_FUNCTION_TRACE_PTR(ex_get_object_reference, obj_desc); 75 76 *return_desc = NULL; 77 78 switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) { 79 case ACPI_DESC_TYPE_OPERAND: 80 81 if (obj_desc->common.type != ACPI_TYPE_LOCAL_REFERENCE) { 82 return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 83 } 84 85 /* 86 * Must be a reference to a Local or Arg 87 */ 88 switch (obj_desc->reference.class) { 89 case ACPI_REFCLASS_LOCAL: 90 case ACPI_REFCLASS_ARG: 91 case ACPI_REFCLASS_DEBUG: 92 93 /* The referenced object is the pseudo-node for the local/arg */ 94 95 referenced_obj = obj_desc->reference.object; 96 break; 97 98 default: 99 100 ACPI_ERROR((AE_INFO, "Invalid Reference Class 0x%2.2X", 101 obj_desc->reference.class)); 102 return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 103 } 104 break; 105 106 case ACPI_DESC_TYPE_NAMED: 107 /* 108 * A named reference that has already been resolved to a Node 109 */ 110 referenced_obj = obj_desc; 111 break; 112 113 default: 114 115 ACPI_ERROR((AE_INFO, "Invalid descriptor type 0x%X", 116 ACPI_GET_DESCRIPTOR_TYPE(obj_desc))); 117 return_ACPI_STATUS(AE_TYPE); 118 } 119 120 /* Create a new reference object */ 121 122 reference_obj = 123 acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE); 124 if (!reference_obj) { 125 return_ACPI_STATUS(AE_NO_MEMORY); 126 } 127 128 reference_obj->reference.class = ACPI_REFCLASS_REFOF; 129 reference_obj->reference.object = referenced_obj; 130 *return_desc = reference_obj; 131 132 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 133 "Object %p Type [%s], returning Reference %p\n", 134 obj_desc, acpi_ut_get_object_type_name(obj_desc), 135 *return_desc)); 136 137 return_ACPI_STATUS(AE_OK); 138 } 139 140 /******************************************************************************* 141 * 142 * FUNCTION: acpi_ex_do_math_op 143 * 144 * PARAMETERS: opcode - AML opcode 145 * integer0 - Integer operand #0 146 * integer1 - Integer operand #1 147 * 148 * RETURN: Integer result of the operation 149 * 150 * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the 151 * math functions here is to prevent a lot of pointer dereferencing 152 * to obtain the operands. 153 * 154 ******************************************************************************/ 155 156 u64 acpi_ex_do_math_op(u16 opcode, u64 integer0, u64 integer1) 157 { 158 159 ACPI_FUNCTION_ENTRY(); 160 161 switch (opcode) { 162 case AML_ADD_OP: /* Add (Integer0, Integer1, Result) */ 163 164 return (integer0 + integer1); 165 166 case AML_BIT_AND_OP: /* And (Integer0, Integer1, Result) */ 167 168 return (integer0 & integer1); 169 170 case AML_BIT_NAND_OP: /* NAnd (Integer0, Integer1, Result) */ 171 172 return (~(integer0 & integer1)); 173 174 case AML_BIT_OR_OP: /* Or (Integer0, Integer1, Result) */ 175 176 return (integer0 | integer1); 177 178 case AML_BIT_NOR_OP: /* NOr (Integer0, Integer1, Result) */ 179 180 return (~(integer0 | integer1)); 181 182 case AML_BIT_XOR_OP: /* XOr (Integer0, Integer1, Result) */ 183 184 return (integer0 ^ integer1); 185 186 case AML_MULTIPLY_OP: /* Multiply (Integer0, Integer1, Result) */ 187 188 return (integer0 * integer1); 189 190 case AML_SHIFT_LEFT_OP: /* shift_left (Operand, shift_count, Result) */ 191 192 /* 193 * We need to check if the shiftcount is larger than the integer bit 194 * width since the behavior of this is not well-defined in the C language. 195 */ 196 if (integer1 >= acpi_gbl_integer_bit_width) { 197 return (0); 198 } 199 return (integer0 << integer1); 200 201 case AML_SHIFT_RIGHT_OP: /* shift_right (Operand, shift_count, Result) */ 202 203 /* 204 * We need to check if the shiftcount is larger than the integer bit 205 * width since the behavior of this is not well-defined in the C language. 206 */ 207 if (integer1 >= acpi_gbl_integer_bit_width) { 208 return (0); 209 } 210 return (integer0 >> integer1); 211 212 case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */ 213 214 return (integer0 - integer1); 215 216 default: 217 218 return (0); 219 } 220 } 221 222 /******************************************************************************* 223 * 224 * FUNCTION: acpi_ex_do_logical_numeric_op 225 * 226 * PARAMETERS: opcode - AML opcode 227 * integer0 - Integer operand #0 228 * integer1 - Integer operand #1 229 * logical_result - TRUE/FALSE result of the operation 230 * 231 * RETURN: Status 232 * 233 * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric 234 * operators (LAnd and LOr), both operands must be integers. 235 * 236 * Note: cleanest machine code seems to be produced by the code 237 * below, rather than using statements of the form: 238 * Result = (Integer0 && Integer1); 239 * 240 ******************************************************************************/ 241 242 acpi_status 243 acpi_ex_do_logical_numeric_op(u16 opcode, 244 u64 integer0, u64 integer1, u8 *logical_result) 245 { 246 acpi_status status = AE_OK; 247 u8 local_result = FALSE; 248 249 ACPI_FUNCTION_TRACE(ex_do_logical_numeric_op); 250 251 switch (opcode) { 252 case AML_LAND_OP: /* LAnd (Integer0, Integer1) */ 253 254 if (integer0 && integer1) { 255 local_result = TRUE; 256 } 257 break; 258 259 case AML_LOR_OP: /* LOr (Integer0, Integer1) */ 260 261 if (integer0 || integer1) { 262 local_result = TRUE; 263 } 264 break; 265 266 default: 267 268 status = AE_AML_INTERNAL; 269 break; 270 } 271 272 /* Return the logical result and status */ 273 274 *logical_result = local_result; 275 return_ACPI_STATUS(status); 276 } 277 278 /******************************************************************************* 279 * 280 * FUNCTION: acpi_ex_do_logical_op 281 * 282 * PARAMETERS: opcode - AML opcode 283 * operand0 - operand #0 284 * operand1 - operand #1 285 * logical_result - TRUE/FALSE result of the operation 286 * 287 * RETURN: Status 288 * 289 * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the 290 * functions here is to prevent a lot of pointer dereferencing 291 * to obtain the operands and to simplify the generation of the 292 * logical value. For the Numeric operators (LAnd and LOr), both 293 * operands must be integers. For the other logical operators, 294 * operands can be any combination of Integer/String/Buffer. The 295 * first operand determines the type to which the second operand 296 * will be converted. 297 * 298 * Note: cleanest machine code seems to be produced by the code 299 * below, rather than using statements of the form: 300 * Result = (Operand0 == Operand1); 301 * 302 ******************************************************************************/ 303 304 acpi_status 305 acpi_ex_do_logical_op(u16 opcode, 306 union acpi_operand_object *operand0, 307 union acpi_operand_object *operand1, u8 * logical_result) 308 { 309 union acpi_operand_object *local_operand1 = operand1; 310 u64 integer0; 311 u64 integer1; 312 u32 length0; 313 u32 length1; 314 acpi_status status = AE_OK; 315 u8 local_result = FALSE; 316 int compare; 317 318 ACPI_FUNCTION_TRACE(ex_do_logical_op); 319 320 /* 321 * Convert the second operand if necessary. The first operand 322 * determines the type of the second operand, (See the Data Types 323 * section of the ACPI 3.0+ specification.) Both object types are 324 * guaranteed to be either Integer/String/Buffer by the operand 325 * resolution mechanism. 326 */ 327 switch (operand0->common.type) { 328 case ACPI_TYPE_INTEGER: 329 330 status = 331 acpi_ex_convert_to_integer(operand1, &local_operand1, 16); 332 break; 333 334 case ACPI_TYPE_STRING: 335 336 status = 337 acpi_ex_convert_to_string(operand1, &local_operand1, 338 ACPI_IMPLICIT_CONVERT_HEX); 339 break; 340 341 case ACPI_TYPE_BUFFER: 342 343 status = acpi_ex_convert_to_buffer(operand1, &local_operand1); 344 break; 345 346 default: 347 348 status = AE_AML_INTERNAL; 349 break; 350 } 351 352 if (ACPI_FAILURE(status)) { 353 goto cleanup; 354 } 355 356 /* 357 * Two cases: 1) Both Integers, 2) Both Strings or Buffers 358 */ 359 if (operand0->common.type == ACPI_TYPE_INTEGER) { 360 /* 361 * 1) Both operands are of type integer 362 * Note: local_operand1 may have changed above 363 */ 364 integer0 = operand0->integer.value; 365 integer1 = local_operand1->integer.value; 366 367 switch (opcode) { 368 case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ 369 370 if (integer0 == integer1) { 371 local_result = TRUE; 372 } 373 break; 374 375 case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ 376 377 if (integer0 > integer1) { 378 local_result = TRUE; 379 } 380 break; 381 382 case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ 383 384 if (integer0 < integer1) { 385 local_result = TRUE; 386 } 387 break; 388 389 default: 390 391 status = AE_AML_INTERNAL; 392 break; 393 } 394 } else { 395 /* 396 * 2) Both operands are Strings or both are Buffers 397 * Note: Code below takes advantage of common Buffer/String 398 * object fields. local_operand1 may have changed above. Use 399 * memcmp to handle nulls in buffers. 400 */ 401 length0 = operand0->buffer.length; 402 length1 = local_operand1->buffer.length; 403 404 /* Lexicographic compare: compare the data bytes */ 405 406 compare = memcmp(operand0->buffer.pointer, 407 local_operand1->buffer.pointer, 408 (length0 > length1) ? length1 : length0); 409 410 switch (opcode) { 411 case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ 412 413 /* Length and all bytes must be equal */ 414 415 if ((length0 == length1) && (compare == 0)) { 416 417 /* Length and all bytes match ==> TRUE */ 418 419 local_result = TRUE; 420 } 421 break; 422 423 case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ 424 425 if (compare > 0) { 426 local_result = TRUE; 427 goto cleanup; /* TRUE */ 428 } 429 if (compare < 0) { 430 goto cleanup; /* FALSE */ 431 } 432 433 /* Bytes match (to shortest length), compare lengths */ 434 435 if (length0 > length1) { 436 local_result = TRUE; 437 } 438 break; 439 440 case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ 441 442 if (compare > 0) { 443 goto cleanup; /* FALSE */ 444 } 445 if (compare < 0) { 446 local_result = TRUE; 447 goto cleanup; /* TRUE */ 448 } 449 450 /* Bytes match (to shortest length), compare lengths */ 451 452 if (length0 < length1) { 453 local_result = TRUE; 454 } 455 break; 456 457 default: 458 459 status = AE_AML_INTERNAL; 460 break; 461 } 462 } 463 464 cleanup: 465 466 /* New object was created if implicit conversion performed - delete */ 467 468 if (local_operand1 != operand1) { 469 acpi_ut_remove_reference(local_operand1); 470 } 471 472 /* Return the logical result and status */ 473 474 *logical_result = local_result; 475 return_ACPI_STATUS(status); 476 } 477