1 /****************************************************************************** 2 * 3 * Module Name: exoparg2 - AML execution - opcodes with 2 arguments 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2008, 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 "acparser.h" 47 #include "acinterp.h" 48 #include "acevents.h" 49 #include "amlcode.h" 50 51 #define _COMPONENT ACPI_EXECUTER 52 ACPI_MODULE_NAME("exoparg2") 53 54 /*! 55 * Naming convention for AML interpreter execution routines. 56 * 57 * The routines that begin execution of AML opcodes are named with a common 58 * convention based upon the number of arguments, the number of target operands, 59 * and whether or not a value is returned: 60 * 61 * AcpiExOpcode_xA_yT_zR 62 * 63 * Where: 64 * 65 * xA - ARGUMENTS: The number of arguments (input operands) that are 66 * required for this opcode type (1 through 6 args). 67 * yT - TARGETS: The number of targets (output operands) that are required 68 * for this opcode type (0, 1, or 2 targets). 69 * zR - RETURN VALUE: Indicates whether this opcode type returns a value 70 * as the function return (0 or 1). 71 * 72 * The AcpiExOpcode* functions are called via the Dispatcher component with 73 * fully resolved operands. 74 !*/ 75 /******************************************************************************* 76 * 77 * FUNCTION: acpi_ex_opcode_2A_0T_0R 78 * 79 * PARAMETERS: walk_state - Current walk state 80 * 81 * RETURN: Status 82 * 83 * DESCRIPTION: Execute opcode with two arguments, no target, and no return 84 * value. 85 * 86 * ALLOCATION: Deletes both operands 87 * 88 ******************************************************************************/ 89 acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state) 90 { 91 union acpi_operand_object **operand = &walk_state->operands[0]; 92 struct acpi_namespace_node *node; 93 u32 value; 94 acpi_status status = AE_OK; 95 96 ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_0R, 97 acpi_ps_get_opcode_name(walk_state->opcode)); 98 99 /* Examine the opcode */ 100 101 switch (walk_state->opcode) { 102 case AML_NOTIFY_OP: /* Notify (notify_object, notify_value) */ 103 104 /* The first operand is a namespace node */ 105 106 node = (struct acpi_namespace_node *)operand[0]; 107 108 /* Second value is the notify value */ 109 110 value = (u32) operand[1]->integer.value; 111 112 /* Are notifies allowed on this object? */ 113 114 if (!acpi_ev_is_notify_object(node)) { 115 ACPI_ERROR((AE_INFO, 116 "Unexpected notify object type [%s]", 117 acpi_ut_get_type_name(node->type))); 118 119 status = AE_AML_OPERAND_TYPE; 120 break; 121 } 122 #ifdef ACPI_GPE_NOTIFY_CHECK 123 /* 124 * GPE method wake/notify check. Here, we want to ensure that we 125 * don't receive any "DeviceWake" Notifies from a GPE _Lxx or _Exx 126 * GPE method during system runtime. If we do, the GPE is marked 127 * as "wake-only" and disabled. 128 * 129 * 1) Is the Notify() value == device_wake? 130 * 2) Is this a GPE deferred method? (An _Lxx or _Exx method) 131 * 3) Did the original GPE happen at system runtime? 132 * (versus during wake) 133 * 134 * If all three cases are true, this is a wake-only GPE that should 135 * be disabled at runtime. 136 */ 137 if (value == 2) { /* device_wake */ 138 status = 139 acpi_ev_check_for_wake_only_gpe(walk_state-> 140 gpe_event_info); 141 if (ACPI_FAILURE(status)) { 142 143 /* AE_WAKE_ONLY_GPE only error, means ignore this notify */ 144 145 return_ACPI_STATUS(AE_OK) 146 } 147 } 148 #endif 149 150 /* 151 * Dispatch the notify to the appropriate handler 152 * NOTE: the request is queued for execution after this method 153 * completes. The notify handlers are NOT invoked synchronously 154 * from this thread -- because handlers may in turn run other 155 * control methods. 156 */ 157 status = acpi_ev_queue_notify_request(node, value); 158 break; 159 160 default: 161 162 ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", 163 walk_state->opcode)); 164 status = AE_AML_BAD_OPCODE; 165 } 166 167 return_ACPI_STATUS(status); 168 } 169 170 /******************************************************************************* 171 * 172 * FUNCTION: acpi_ex_opcode_2A_2T_1R 173 * 174 * PARAMETERS: walk_state - Current walk state 175 * 176 * RETURN: Status 177 * 178 * DESCRIPTION: Execute a dyadic operator (2 operands) with 2 output targets 179 * and one implicit return value. 180 * 181 ******************************************************************************/ 182 183 acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state) 184 { 185 union acpi_operand_object **operand = &walk_state->operands[0]; 186 union acpi_operand_object *return_desc1 = NULL; 187 union acpi_operand_object *return_desc2 = NULL; 188 acpi_status status; 189 190 ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_2T_1R, 191 acpi_ps_get_opcode_name(walk_state->opcode)); 192 193 /* Execute the opcode */ 194 195 switch (walk_state->opcode) { 196 case AML_DIVIDE_OP: 197 198 /* Divide (Dividend, Divisor, remainder_result quotient_result) */ 199 200 return_desc1 = 201 acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); 202 if (!return_desc1) { 203 status = AE_NO_MEMORY; 204 goto cleanup; 205 } 206 207 return_desc2 = 208 acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); 209 if (!return_desc2) { 210 status = AE_NO_MEMORY; 211 goto cleanup; 212 } 213 214 /* Quotient to return_desc1, remainder to return_desc2 */ 215 216 status = acpi_ut_divide(operand[0]->integer.value, 217 operand[1]->integer.value, 218 &return_desc1->integer.value, 219 &return_desc2->integer.value); 220 if (ACPI_FAILURE(status)) { 221 goto cleanup; 222 } 223 break; 224 225 default: 226 227 ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", 228 walk_state->opcode)); 229 status = AE_AML_BAD_OPCODE; 230 goto cleanup; 231 } 232 233 /* Store the results to the target reference operands */ 234 235 status = acpi_ex_store(return_desc2, operand[2], walk_state); 236 if (ACPI_FAILURE(status)) { 237 goto cleanup; 238 } 239 240 status = acpi_ex_store(return_desc1, operand[3], walk_state); 241 if (ACPI_FAILURE(status)) { 242 goto cleanup; 243 } 244 245 cleanup: 246 /* 247 * Since the remainder is not returned indirectly, remove a reference to 248 * it. Only the quotient is returned indirectly. 249 */ 250 acpi_ut_remove_reference(return_desc2); 251 252 if (ACPI_FAILURE(status)) { 253 254 /* Delete the return object */ 255 256 acpi_ut_remove_reference(return_desc1); 257 } 258 259 /* Save return object (the remainder) on success */ 260 261 else { 262 walk_state->result_obj = return_desc1; 263 } 264 265 return_ACPI_STATUS(status); 266 } 267 268 /******************************************************************************* 269 * 270 * FUNCTION: acpi_ex_opcode_2A_1T_1R 271 * 272 * PARAMETERS: walk_state - Current walk state 273 * 274 * RETURN: Status 275 * 276 * DESCRIPTION: Execute opcode with two arguments, one target, and a return 277 * value. 278 * 279 ******************************************************************************/ 280 281 acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) 282 { 283 union acpi_operand_object **operand = &walk_state->operands[0]; 284 union acpi_operand_object *return_desc = NULL; 285 acpi_integer index; 286 acpi_status status = AE_OK; 287 acpi_size length; 288 289 ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_1T_1R, 290 acpi_ps_get_opcode_name(walk_state->opcode)); 291 292 /* Execute the opcode */ 293 294 if (walk_state->op_info->flags & AML_MATH) { 295 296 /* All simple math opcodes (add, etc.) */ 297 298 return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); 299 if (!return_desc) { 300 status = AE_NO_MEMORY; 301 goto cleanup; 302 } 303 304 return_desc->integer.value = 305 acpi_ex_do_math_op(walk_state->opcode, 306 operand[0]->integer.value, 307 operand[1]->integer.value); 308 goto store_result_to_target; 309 } 310 311 switch (walk_state->opcode) { 312 case AML_MOD_OP: /* Mod (Dividend, Divisor, remainder_result (ACPI 2.0) */ 313 314 return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); 315 if (!return_desc) { 316 status = AE_NO_MEMORY; 317 goto cleanup; 318 } 319 320 /* return_desc will contain the remainder */ 321 322 status = acpi_ut_divide(operand[0]->integer.value, 323 operand[1]->integer.value, 324 NULL, &return_desc->integer.value); 325 break; 326 327 case AML_CONCAT_OP: /* Concatenate (Data1, Data2, Result) */ 328 329 status = acpi_ex_do_concatenate(operand[0], operand[1], 330 &return_desc, walk_state); 331 break; 332 333 case AML_TO_STRING_OP: /* to_string (Buffer, Length, Result) (ACPI 2.0) */ 334 335 /* 336 * Input object is guaranteed to be a buffer at this point (it may have 337 * been converted.) Copy the raw buffer data to a new object of 338 * type String. 339 */ 340 341 /* 342 * Get the length of the new string. It is the smallest of: 343 * 1) Length of the input buffer 344 * 2) Max length as specified in the to_string operator 345 * 3) Length of input buffer up to a zero byte (null terminator) 346 * 347 * NOTE: A length of zero is ok, and will create a zero-length, null 348 * terminated string. 349 */ 350 length = 0; 351 while ((length < operand[0]->buffer.length) && 352 (length < operand[1]->integer.value) && 353 (operand[0]->buffer.pointer[length])) { 354 length++; 355 } 356 357 /* Allocate a new string object */ 358 359 return_desc = acpi_ut_create_string_object(length); 360 if (!return_desc) { 361 status = AE_NO_MEMORY; 362 goto cleanup; 363 } 364 365 /* 366 * Copy the raw buffer data with no transform. 367 * (NULL terminated already) 368 */ 369 ACPI_MEMCPY(return_desc->string.pointer, 370 operand[0]->buffer.pointer, length); 371 break; 372 373 case AML_CONCAT_RES_OP: 374 375 /* concatenate_res_template (Buffer, Buffer, Result) (ACPI 2.0) */ 376 377 status = acpi_ex_concat_template(operand[0], operand[1], 378 &return_desc, walk_state); 379 break; 380 381 case AML_INDEX_OP: /* Index (Source Index Result) */ 382 383 /* Create the internal return object */ 384 385 return_desc = 386 acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE); 387 if (!return_desc) { 388 status = AE_NO_MEMORY; 389 goto cleanup; 390 } 391 392 /* Initialize the Index reference object */ 393 394 index = operand[1]->integer.value; 395 return_desc->reference.value = (u32) index; 396 return_desc->reference.class = ACPI_REFCLASS_INDEX; 397 398 /* 399 * At this point, the Source operand is a String, Buffer, or Package. 400 * Verify that the index is within range. 401 */ 402 switch ((operand[0])->common.type) { 403 case ACPI_TYPE_STRING: 404 405 if (index >= operand[0]->string.length) { 406 status = AE_AML_STRING_LIMIT; 407 } 408 409 return_desc->reference.target_type = 410 ACPI_TYPE_BUFFER_FIELD; 411 break; 412 413 case ACPI_TYPE_BUFFER: 414 415 if (index >= operand[0]->buffer.length) { 416 status = AE_AML_BUFFER_LIMIT; 417 } 418 419 return_desc->reference.target_type = 420 ACPI_TYPE_BUFFER_FIELD; 421 break; 422 423 case ACPI_TYPE_PACKAGE: 424 425 if (index >= operand[0]->package.count) { 426 status = AE_AML_PACKAGE_LIMIT; 427 } 428 429 return_desc->reference.target_type = ACPI_TYPE_PACKAGE; 430 return_desc->reference.where = 431 &operand[0]->package.elements[index]; 432 break; 433 434 default: 435 436 status = AE_AML_INTERNAL; 437 goto cleanup; 438 } 439 440 /* Failure means that the Index was beyond the end of the object */ 441 442 if (ACPI_FAILURE(status)) { 443 ACPI_EXCEPTION((AE_INFO, status, 444 "Index (%X%8.8X) is beyond end of object", 445 ACPI_FORMAT_UINT64(index))); 446 goto cleanup; 447 } 448 449 /* 450 * Save the target object and add a reference to it for the life 451 * of the index 452 */ 453 return_desc->reference.object = operand[0]; 454 acpi_ut_add_reference(operand[0]); 455 456 /* Store the reference to the Target */ 457 458 status = acpi_ex_store(return_desc, operand[2], walk_state); 459 460 /* Return the reference */ 461 462 walk_state->result_obj = return_desc; 463 goto cleanup; 464 465 default: 466 467 ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", 468 walk_state->opcode)); 469 status = AE_AML_BAD_OPCODE; 470 break; 471 } 472 473 store_result_to_target: 474 475 if (ACPI_SUCCESS(status)) { 476 /* 477 * Store the result of the operation (which is now in return_desc) into 478 * the Target descriptor. 479 */ 480 status = acpi_ex_store(return_desc, operand[2], walk_state); 481 if (ACPI_FAILURE(status)) { 482 goto cleanup; 483 } 484 485 if (!walk_state->result_obj) { 486 walk_state->result_obj = return_desc; 487 } 488 } 489 490 cleanup: 491 492 /* Delete return object on error */ 493 494 if (ACPI_FAILURE(status)) { 495 acpi_ut_remove_reference(return_desc); 496 walk_state->result_obj = NULL; 497 } 498 499 return_ACPI_STATUS(status); 500 } 501 502 /******************************************************************************* 503 * 504 * FUNCTION: acpi_ex_opcode_2A_0T_1R 505 * 506 * PARAMETERS: walk_state - Current walk state 507 * 508 * RETURN: Status 509 * 510 * DESCRIPTION: Execute opcode with 2 arguments, no target, and a return value 511 * 512 ******************************************************************************/ 513 514 acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state) 515 { 516 union acpi_operand_object **operand = &walk_state->operands[0]; 517 union acpi_operand_object *return_desc = NULL; 518 acpi_status status = AE_OK; 519 u8 logical_result = FALSE; 520 521 ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_1R, 522 acpi_ps_get_opcode_name(walk_state->opcode)); 523 524 /* Create the internal return object */ 525 526 return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); 527 if (!return_desc) { 528 status = AE_NO_MEMORY; 529 goto cleanup; 530 } 531 532 /* Execute the Opcode */ 533 534 if (walk_state->op_info->flags & AML_LOGICAL_NUMERIC) { 535 536 /* logical_op (Operand0, Operand1) */ 537 538 status = acpi_ex_do_logical_numeric_op(walk_state->opcode, 539 operand[0]->integer. 540 value, 541 operand[1]->integer. 542 value, &logical_result); 543 goto store_logical_result; 544 } else if (walk_state->op_info->flags & AML_LOGICAL) { 545 546 /* logical_op (Operand0, Operand1) */ 547 548 status = acpi_ex_do_logical_op(walk_state->opcode, operand[0], 549 operand[1], &logical_result); 550 goto store_logical_result; 551 } 552 553 switch (walk_state->opcode) { 554 case AML_ACQUIRE_OP: /* Acquire (mutex_object, Timeout) */ 555 556 status = 557 acpi_ex_acquire_mutex(operand[1], operand[0], walk_state); 558 if (status == AE_TIME) { 559 logical_result = TRUE; /* TRUE = Acquire timed out */ 560 status = AE_OK; 561 } 562 break; 563 564 case AML_WAIT_OP: /* Wait (event_object, Timeout) */ 565 566 status = acpi_ex_system_wait_event(operand[1], operand[0]); 567 if (status == AE_TIME) { 568 logical_result = TRUE; /* TRUE, Wait timed out */ 569 status = AE_OK; 570 } 571 break; 572 573 default: 574 575 ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", 576 walk_state->opcode)); 577 status = AE_AML_BAD_OPCODE; 578 goto cleanup; 579 } 580 581 store_logical_result: 582 /* 583 * Set return value to according to logical_result. logical TRUE (all ones) 584 * Default is FALSE (zero) 585 */ 586 if (logical_result) { 587 return_desc->integer.value = ACPI_INTEGER_MAX; 588 } 589 590 cleanup: 591 592 /* Delete return object on error */ 593 594 if (ACPI_FAILURE(status)) { 595 acpi_ut_remove_reference(return_desc); 596 } 597 598 /* Save return object on success */ 599 600 else { 601 walk_state->result_obj = return_desc; 602 } 603 604 return_ACPI_STATUS(status); 605 } 606