1 /****************************************************************************** 2 * 3 * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2018, 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_LOGICAL_AND_OP: /* LAnd (Integer0, Integer1) */ 253 254 if (integer0 && integer1) { 255 local_result = TRUE; 256 } 257 break; 258 259 case AML_LOGICAL_OR_OP: /* LOr (Integer0, Integer1) */ 260 261 if (integer0 || integer1) { 262 local_result = TRUE; 263 } 264 break; 265 266 default: 267 268 ACPI_ERROR((AE_INFO, 269 "Invalid numeric logical opcode: %X", opcode)); 270 status = AE_AML_INTERNAL; 271 break; 272 } 273 274 /* Return the logical result and status */ 275 276 *logical_result = local_result; 277 return_ACPI_STATUS(status); 278 } 279 280 /******************************************************************************* 281 * 282 * FUNCTION: acpi_ex_do_logical_op 283 * 284 * PARAMETERS: opcode - AML opcode 285 * operand0 - operand #0 286 * operand1 - operand #1 287 * logical_result - TRUE/FALSE result of the operation 288 * 289 * RETURN: Status 290 * 291 * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the 292 * functions here is to prevent a lot of pointer dereferencing 293 * to obtain the operands and to simplify the generation of the 294 * logical value. For the Numeric operators (LAnd and LOr), both 295 * operands must be integers. For the other logical operators, 296 * operands can be any combination of Integer/String/Buffer. The 297 * first operand determines the type to which the second operand 298 * will be converted. 299 * 300 * Note: cleanest machine code seems to be produced by the code 301 * below, rather than using statements of the form: 302 * Result = (Operand0 == Operand1); 303 * 304 ******************************************************************************/ 305 306 acpi_status 307 acpi_ex_do_logical_op(u16 opcode, 308 union acpi_operand_object *operand0, 309 union acpi_operand_object *operand1, u8 * logical_result) 310 { 311 union acpi_operand_object *local_operand1 = operand1; 312 u64 integer0; 313 u64 integer1; 314 u32 length0; 315 u32 length1; 316 acpi_status status = AE_OK; 317 u8 local_result = FALSE; 318 int compare; 319 320 ACPI_FUNCTION_TRACE(ex_do_logical_op); 321 322 /* 323 * Convert the second operand if necessary. The first operand 324 * determines the type of the second operand, (See the Data Types 325 * section of the ACPI 3.0+ specification.) Both object types are 326 * guaranteed to be either Integer/String/Buffer by the operand 327 * resolution mechanism. 328 */ 329 switch (operand0->common.type) { 330 case ACPI_TYPE_INTEGER: 331 332 status = acpi_ex_convert_to_integer(operand1, &local_operand1, 333 ACPI_IMPLICIT_CONVERSION); 334 break; 335 336 case ACPI_TYPE_STRING: 337 338 status = 339 acpi_ex_convert_to_string(operand1, &local_operand1, 340 ACPI_IMPLICIT_CONVERT_HEX); 341 break; 342 343 case ACPI_TYPE_BUFFER: 344 345 status = acpi_ex_convert_to_buffer(operand1, &local_operand1); 346 break; 347 348 default: 349 350 ACPI_ERROR((AE_INFO, 351 "Invalid object type for logical operator: %X", 352 operand0->common.type)); 353 status = AE_AML_INTERNAL; 354 break; 355 } 356 357 if (ACPI_FAILURE(status)) { 358 goto cleanup; 359 } 360 361 /* 362 * Two cases: 1) Both Integers, 2) Both Strings or Buffers 363 */ 364 if (operand0->common.type == ACPI_TYPE_INTEGER) { 365 /* 366 * 1) Both operands are of type integer 367 * Note: local_operand1 may have changed above 368 */ 369 integer0 = operand0->integer.value; 370 integer1 = local_operand1->integer.value; 371 372 switch (opcode) { 373 case AML_LOGICAL_EQUAL_OP: /* LEqual (Operand0, Operand1) */ 374 375 if (integer0 == integer1) { 376 local_result = TRUE; 377 } 378 break; 379 380 case AML_LOGICAL_GREATER_OP: /* LGreater (Operand0, Operand1) */ 381 382 if (integer0 > integer1) { 383 local_result = TRUE; 384 } 385 break; 386 387 case AML_LOGICAL_LESS_OP: /* LLess (Operand0, Operand1) */ 388 389 if (integer0 < integer1) { 390 local_result = TRUE; 391 } 392 break; 393 394 default: 395 396 ACPI_ERROR((AE_INFO, 397 "Invalid comparison opcode: %X", opcode)); 398 status = AE_AML_INTERNAL; 399 break; 400 } 401 } else { 402 /* 403 * 2) Both operands are Strings or both are Buffers 404 * Note: Code below takes advantage of common Buffer/String 405 * object fields. local_operand1 may have changed above. Use 406 * memcmp to handle nulls in buffers. 407 */ 408 length0 = operand0->buffer.length; 409 length1 = local_operand1->buffer.length; 410 411 /* Lexicographic compare: compare the data bytes */ 412 413 compare = memcmp(operand0->buffer.pointer, 414 local_operand1->buffer.pointer, 415 (length0 > length1) ? length1 : length0); 416 417 switch (opcode) { 418 case AML_LOGICAL_EQUAL_OP: /* LEqual (Operand0, Operand1) */ 419 420 /* Length and all bytes must be equal */ 421 422 if ((length0 == length1) && (compare == 0)) { 423 424 /* Length and all bytes match ==> TRUE */ 425 426 local_result = TRUE; 427 } 428 break; 429 430 case AML_LOGICAL_GREATER_OP: /* LGreater (Operand0, Operand1) */ 431 432 if (compare > 0) { 433 local_result = TRUE; 434 goto cleanup; /* TRUE */ 435 } 436 if (compare < 0) { 437 goto cleanup; /* FALSE */ 438 } 439 440 /* Bytes match (to shortest length), compare lengths */ 441 442 if (length0 > length1) { 443 local_result = TRUE; 444 } 445 break; 446 447 case AML_LOGICAL_LESS_OP: /* LLess (Operand0, Operand1) */ 448 449 if (compare > 0) { 450 goto cleanup; /* FALSE */ 451 } 452 if (compare < 0) { 453 local_result = TRUE; 454 goto cleanup; /* TRUE */ 455 } 456 457 /* Bytes match (to shortest length), compare lengths */ 458 459 if (length0 < length1) { 460 local_result = TRUE; 461 } 462 break; 463 464 default: 465 466 ACPI_ERROR((AE_INFO, 467 "Invalid comparison opcode: %X", opcode)); 468 status = AE_AML_INTERNAL; 469 break; 470 } 471 } 472 473 cleanup: 474 475 /* New object was created if implicit conversion performed - delete */ 476 477 if (local_operand1 != operand1) { 478 acpi_ut_remove_reference(local_operand1); 479 } 480 481 /* Return the logical result and status */ 482 483 *logical_result = local_result; 484 return_ACPI_STATUS(status); 485 } 486