1 /****************************************************************************** 2 * 3 * Module Name: dswexec - Dispatcher method execution callbacks; 4 * dispatch to interpreter. 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2008, 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 #include <acpi/acpi.h> 46 #include "accommon.h" 47 #include "acparser.h" 48 #include "amlcode.h" 49 #include "acdispat.h" 50 #include "acinterp.h" 51 #include "acnamesp.h" 52 #include "acdebug.h" 53 54 #define _COMPONENT ACPI_DISPATCHER 55 ACPI_MODULE_NAME("dswexec") 56 57 /* 58 * Dispatch table for opcode classes 59 */ 60 static ACPI_EXECUTE_OP acpi_gbl_op_type_dispatch[] = { 61 acpi_ex_opcode_0A_0T_1R, 62 acpi_ex_opcode_1A_0T_0R, 63 acpi_ex_opcode_1A_0T_1R, 64 acpi_ex_opcode_1A_1T_0R, 65 acpi_ex_opcode_1A_1T_1R, 66 acpi_ex_opcode_2A_0T_0R, 67 acpi_ex_opcode_2A_0T_1R, 68 acpi_ex_opcode_2A_1T_1R, 69 acpi_ex_opcode_2A_2T_1R, 70 acpi_ex_opcode_3A_0T_0R, 71 acpi_ex_opcode_3A_1T_1R, 72 acpi_ex_opcode_6A_0T_1R 73 }; 74 75 /***************************************************************************** 76 * 77 * FUNCTION: acpi_ds_get_predicate_value 78 * 79 * PARAMETERS: walk_state - Current state of the parse tree walk 80 * result_obj - if non-zero, pop result from result stack 81 * 82 * RETURN: Status 83 * 84 * DESCRIPTION: Get the result of a predicate evaluation 85 * 86 ****************************************************************************/ 87 88 acpi_status 89 acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state, 90 union acpi_operand_object *result_obj) 91 { 92 acpi_status status = AE_OK; 93 union acpi_operand_object *obj_desc; 94 union acpi_operand_object *local_obj_desc = NULL; 95 96 ACPI_FUNCTION_TRACE_PTR(ds_get_predicate_value, walk_state); 97 98 walk_state->control_state->common.state = 0; 99 100 if (result_obj) { 101 status = acpi_ds_result_pop(&obj_desc, walk_state); 102 if (ACPI_FAILURE(status)) { 103 ACPI_EXCEPTION((AE_INFO, status, 104 "Could not get result from predicate evaluation")); 105 106 return_ACPI_STATUS(status); 107 } 108 } else { 109 status = acpi_ds_create_operand(walk_state, walk_state->op, 0); 110 if (ACPI_FAILURE(status)) { 111 return_ACPI_STATUS(status); 112 } 113 114 status = 115 acpi_ex_resolve_to_value(&walk_state->operands[0], 116 walk_state); 117 if (ACPI_FAILURE(status)) { 118 return_ACPI_STATUS(status); 119 } 120 121 obj_desc = walk_state->operands[0]; 122 } 123 124 if (!obj_desc) { 125 ACPI_ERROR((AE_INFO, 126 "No predicate ObjDesc=%p State=%p", 127 obj_desc, walk_state)); 128 129 return_ACPI_STATUS(AE_AML_NO_OPERAND); 130 } 131 132 /* 133 * Result of predicate evaluation must be an Integer 134 * object. Implicitly convert the argument if necessary. 135 */ 136 status = acpi_ex_convert_to_integer(obj_desc, &local_obj_desc, 16); 137 if (ACPI_FAILURE(status)) { 138 goto cleanup; 139 } 140 141 if (local_obj_desc->common.type != ACPI_TYPE_INTEGER) { 142 ACPI_ERROR((AE_INFO, 143 "Bad predicate (not an integer) ObjDesc=%p State=%p Type=%X", 144 obj_desc, walk_state, obj_desc->common.type)); 145 146 status = AE_AML_OPERAND_TYPE; 147 goto cleanup; 148 } 149 150 /* Truncate the predicate to 32-bits if necessary */ 151 152 acpi_ex_truncate_for32bit_table(local_obj_desc); 153 154 /* 155 * Save the result of the predicate evaluation on 156 * the control stack 157 */ 158 if (local_obj_desc->integer.value) { 159 walk_state->control_state->common.value = TRUE; 160 } else { 161 /* 162 * Predicate is FALSE, we will just toss the 163 * rest of the package 164 */ 165 walk_state->control_state->common.value = FALSE; 166 status = AE_CTRL_FALSE; 167 } 168 169 /* Predicate can be used for an implicit return value */ 170 171 (void)acpi_ds_do_implicit_return(local_obj_desc, walk_state, TRUE); 172 173 cleanup: 174 175 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Completed a predicate eval=%X Op=%p\n", 176 walk_state->control_state->common.value, 177 walk_state->op)); 178 179 /* Break to debugger to display result */ 180 181 ACPI_DEBUGGER_EXEC(acpi_db_display_result_object 182 (local_obj_desc, walk_state)); 183 184 /* 185 * Delete the predicate result object (we know that 186 * we don't need it anymore) 187 */ 188 if (local_obj_desc != obj_desc) { 189 acpi_ut_remove_reference(local_obj_desc); 190 } 191 acpi_ut_remove_reference(obj_desc); 192 193 walk_state->control_state->common.state = ACPI_CONTROL_NORMAL; 194 return_ACPI_STATUS(status); 195 } 196 197 /***************************************************************************** 198 * 199 * FUNCTION: acpi_ds_exec_begin_op 200 * 201 * PARAMETERS: walk_state - Current state of the parse tree walk 202 * out_op - Where to return op if a new one is created 203 * 204 * RETURN: Status 205 * 206 * DESCRIPTION: Descending callback used during the execution of control 207 * methods. This is where most operators and operands are 208 * dispatched to the interpreter. 209 * 210 ****************************************************************************/ 211 212 acpi_status 213 acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, 214 union acpi_parse_object **out_op) 215 { 216 union acpi_parse_object *op; 217 acpi_status status = AE_OK; 218 u32 opcode_class; 219 220 ACPI_FUNCTION_TRACE_PTR(ds_exec_begin_op, walk_state); 221 222 op = walk_state->op; 223 if (!op) { 224 status = acpi_ds_load2_begin_op(walk_state, out_op); 225 if (ACPI_FAILURE(status)) { 226 goto error_exit; 227 } 228 229 op = *out_op; 230 walk_state->op = op; 231 walk_state->opcode = op->common.aml_opcode; 232 walk_state->op_info = 233 acpi_ps_get_opcode_info(op->common.aml_opcode); 234 235 if (acpi_ns_opens_scope(walk_state->op_info->object_type)) { 236 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 237 "(%s) Popping scope for Op %p\n", 238 acpi_ut_get_type_name(walk_state-> 239 op_info-> 240 object_type), 241 op)); 242 243 status = acpi_ds_scope_stack_pop(walk_state); 244 if (ACPI_FAILURE(status)) { 245 goto error_exit; 246 } 247 } 248 } 249 250 if (op == walk_state->origin) { 251 if (out_op) { 252 *out_op = op; 253 } 254 255 return_ACPI_STATUS(AE_OK); 256 } 257 258 /* 259 * If the previous opcode was a conditional, this opcode 260 * must be the beginning of the associated predicate. 261 * Save this knowledge in the current scope descriptor 262 */ 263 if ((walk_state->control_state) && 264 (walk_state->control_state->common.state == 265 ACPI_CONTROL_CONDITIONAL_EXECUTING)) { 266 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 267 "Exec predicate Op=%p State=%p\n", op, 268 walk_state)); 269 270 walk_state->control_state->common.state = 271 ACPI_CONTROL_PREDICATE_EXECUTING; 272 273 /* Save start of predicate */ 274 275 walk_state->control_state->control.predicate_op = op; 276 } 277 278 opcode_class = walk_state->op_info->class; 279 280 /* We want to send namepaths to the load code */ 281 282 if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { 283 opcode_class = AML_CLASS_NAMED_OBJECT; 284 } 285 286 /* 287 * Handle the opcode based upon the opcode type 288 */ 289 switch (opcode_class) { 290 case AML_CLASS_CONTROL: 291 292 status = acpi_ds_exec_begin_control_op(walk_state, op); 293 break; 294 295 case AML_CLASS_NAMED_OBJECT: 296 297 if (walk_state->walk_type & ACPI_WALK_METHOD) { 298 /* 299 * Found a named object declaration during method execution; 300 * we must enter this object into the namespace. The created 301 * object is temporary and will be deleted upon completion of 302 * the execution of this method. 303 */ 304 status = acpi_ds_load2_begin_op(walk_state, NULL); 305 } 306 307 break; 308 309 case AML_CLASS_EXECUTE: 310 case AML_CLASS_CREATE: 311 312 break; 313 314 default: 315 break; 316 } 317 318 /* Nothing to do here during method execution */ 319 320 return_ACPI_STATUS(status); 321 322 error_exit: 323 status = acpi_ds_method_error(status, walk_state); 324 return_ACPI_STATUS(status); 325 } 326 327 /***************************************************************************** 328 * 329 * FUNCTION: acpi_ds_exec_end_op 330 * 331 * PARAMETERS: walk_state - Current state of the parse tree walk 332 * 333 * RETURN: Status 334 * 335 * DESCRIPTION: Ascending callback used during the execution of control 336 * methods. The only thing we really need to do here is to 337 * notice the beginning of IF, ELSE, and WHILE blocks. 338 * 339 ****************************************************************************/ 340 341 acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) 342 { 343 union acpi_parse_object *op; 344 acpi_status status = AE_OK; 345 u32 op_type; 346 u32 op_class; 347 union acpi_parse_object *next_op; 348 union acpi_parse_object *first_arg; 349 350 ACPI_FUNCTION_TRACE_PTR(ds_exec_end_op, walk_state); 351 352 op = walk_state->op; 353 op_type = walk_state->op_info->type; 354 op_class = walk_state->op_info->class; 355 356 if (op_class == AML_CLASS_UNKNOWN) { 357 ACPI_ERROR((AE_INFO, "Unknown opcode %X", 358 op->common.aml_opcode)); 359 return_ACPI_STATUS(AE_NOT_IMPLEMENTED); 360 } 361 362 first_arg = op->common.value.arg; 363 364 /* Init the walk state */ 365 366 walk_state->num_operands = 0; 367 walk_state->operand_index = 0; 368 walk_state->return_desc = NULL; 369 walk_state->result_obj = NULL; 370 371 /* Call debugger for single step support (DEBUG build only) */ 372 373 ACPI_DEBUGGER_EXEC(status = 374 acpi_db_single_step(walk_state, op, op_class)); 375 ACPI_DEBUGGER_EXEC(if (ACPI_FAILURE(status)) { 376 return_ACPI_STATUS(status);} 377 ) ; 378 379 /* Decode the Opcode Class */ 380 381 switch (op_class) { 382 case AML_CLASS_ARGUMENT: /* Constants, literals, etc. */ 383 384 if (walk_state->opcode == AML_INT_NAMEPATH_OP) { 385 status = acpi_ds_evaluate_name_path(walk_state); 386 if (ACPI_FAILURE(status)) { 387 goto cleanup; 388 } 389 } 390 break; 391 392 case AML_CLASS_EXECUTE: /* Most operators with arguments */ 393 394 /* Build resolved operand stack */ 395 396 status = acpi_ds_create_operands(walk_state, first_arg); 397 if (ACPI_FAILURE(status)) { 398 goto cleanup; 399 } 400 401 /* 402 * All opcodes require operand resolution, with the only exceptions 403 * being the object_type and size_of operators. 404 */ 405 if (!(walk_state->op_info->flags & AML_NO_OPERAND_RESOLVE)) { 406 407 /* Resolve all operands */ 408 409 status = acpi_ex_resolve_operands(walk_state->opcode, 410 &(walk_state-> 411 operands 412 [walk_state-> 413 num_operands - 1]), 414 walk_state); 415 } 416 417 if (ACPI_SUCCESS(status)) { 418 /* 419 * Dispatch the request to the appropriate interpreter handler 420 * routine. There is one routine per opcode "type" based upon the 421 * number of opcode arguments and return type. 422 */ 423 status = 424 acpi_gbl_op_type_dispatch[op_type] (walk_state); 425 } else { 426 /* 427 * Treat constructs of the form "Store(LocalX,LocalX)" as noops when the 428 * Local is uninitialized. 429 */ 430 if ((status == AE_AML_UNINITIALIZED_LOCAL) && 431 (walk_state->opcode == AML_STORE_OP) && 432 (walk_state->operands[0]->common.type == 433 ACPI_TYPE_LOCAL_REFERENCE) 434 && (walk_state->operands[1]->common.type == 435 ACPI_TYPE_LOCAL_REFERENCE) 436 && (walk_state->operands[0]->reference.class == 437 walk_state->operands[1]->reference.class) 438 && (walk_state->operands[0]->reference.value == 439 walk_state->operands[1]->reference.value)) { 440 status = AE_OK; 441 } else { 442 ACPI_EXCEPTION((AE_INFO, status, 443 "While resolving operands for [%s]", 444 acpi_ps_get_opcode_name 445 (walk_state->opcode))); 446 } 447 } 448 449 /* Always delete the argument objects and clear the operand stack */ 450 451 acpi_ds_clear_operands(walk_state); 452 453 /* 454 * If a result object was returned from above, push it on the 455 * current result stack 456 */ 457 if (ACPI_SUCCESS(status) && walk_state->result_obj) { 458 status = 459 acpi_ds_result_push(walk_state->result_obj, 460 walk_state); 461 } 462 break; 463 464 default: 465 466 switch (op_type) { 467 case AML_TYPE_CONTROL: /* Type 1 opcode, IF/ELSE/WHILE/NOOP */ 468 469 /* 1 Operand, 0 external_result, 0 internal_result */ 470 471 status = acpi_ds_exec_end_control_op(walk_state, op); 472 473 break; 474 475 case AML_TYPE_METHOD_CALL: 476 477 /* 478 * If the method is referenced from within a package 479 * declaration, it is not a invocation of the method, just 480 * a reference to it. 481 */ 482 if ((op->asl.parent) && 483 ((op->asl.parent->asl.aml_opcode == AML_PACKAGE_OP) 484 || (op->asl.parent->asl.aml_opcode == 485 AML_VAR_PACKAGE_OP))) { 486 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 487 "Method Reference in a Package, Op=%p\n", 488 op)); 489 490 op->common.node = 491 (struct acpi_namespace_node *)op->asl.value. 492 arg->asl.node; 493 acpi_ut_add_reference(op->asl.value.arg->asl. 494 node->object); 495 return_ACPI_STATUS(AE_OK); 496 } 497 498 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 499 "Method invocation, Op=%p\n", op)); 500 501 /* 502 * (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains 503 * the method Node pointer 504 */ 505 /* next_op points to the op that holds the method name */ 506 507 next_op = first_arg; 508 509 /* next_op points to first argument op */ 510 511 next_op = next_op->common.next; 512 513 /* 514 * Get the method's arguments and put them on the operand stack 515 */ 516 status = acpi_ds_create_operands(walk_state, next_op); 517 if (ACPI_FAILURE(status)) { 518 break; 519 } 520 521 /* 522 * Since the operands will be passed to another control method, 523 * we must resolve all local references here (Local variables, 524 * arguments to *this* method, etc.) 525 */ 526 status = acpi_ds_resolve_operands(walk_state); 527 if (ACPI_FAILURE(status)) { 528 529 /* On error, clear all resolved operands */ 530 531 acpi_ds_clear_operands(walk_state); 532 break; 533 } 534 535 /* 536 * Tell the walk loop to preempt this running method and 537 * execute the new method 538 */ 539 status = AE_CTRL_TRANSFER; 540 541 /* 542 * Return now; we don't want to disturb anything, 543 * especially the operand count! 544 */ 545 return_ACPI_STATUS(status); 546 547 case AML_TYPE_CREATE_FIELD: 548 549 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 550 "Executing CreateField Buffer/Index Op=%p\n", 551 op)); 552 553 status = acpi_ds_load2_end_op(walk_state); 554 if (ACPI_FAILURE(status)) { 555 break; 556 } 557 558 status = 559 acpi_ds_eval_buffer_field_operands(walk_state, op); 560 break; 561 562 case AML_TYPE_CREATE_OBJECT: 563 564 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 565 "Executing CreateObject (Buffer/Package) Op=%p\n", 566 op)); 567 568 switch (op->common.parent->common.aml_opcode) { 569 case AML_NAME_OP: 570 571 /* 572 * Put the Node on the object stack (Contains the ACPI Name 573 * of this object) 574 */ 575 walk_state->operands[0] = 576 (void *)op->common.parent->common.node; 577 walk_state->num_operands = 1; 578 579 status = acpi_ds_create_node(walk_state, 580 op->common.parent-> 581 common.node, 582 op->common.parent); 583 if (ACPI_FAILURE(status)) { 584 break; 585 } 586 587 /* Fall through */ 588 /*lint -fallthrough */ 589 590 case AML_INT_EVAL_SUBTREE_OP: 591 592 status = 593 acpi_ds_eval_data_object_operands 594 (walk_state, op, 595 acpi_ns_get_attached_object(op->common. 596 parent->common. 597 node)); 598 break; 599 600 default: 601 602 status = 603 acpi_ds_eval_data_object_operands 604 (walk_state, op, NULL); 605 break; 606 } 607 608 /* 609 * If a result object was returned from above, push it on the 610 * current result stack 611 */ 612 if (walk_state->result_obj) { 613 status = 614 acpi_ds_result_push(walk_state->result_obj, 615 walk_state); 616 } 617 break; 618 619 case AML_TYPE_NAMED_FIELD: 620 case AML_TYPE_NAMED_COMPLEX: 621 case AML_TYPE_NAMED_SIMPLE: 622 case AML_TYPE_NAMED_NO_OBJ: 623 624 status = acpi_ds_load2_end_op(walk_state); 625 if (ACPI_FAILURE(status)) { 626 break; 627 } 628 629 if (op->common.aml_opcode == AML_REGION_OP) { 630 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 631 "Executing OpRegion Address/Length Op=%p\n", 632 op)); 633 634 status = 635 acpi_ds_eval_region_operands(walk_state, 636 op); 637 if (ACPI_FAILURE(status)) { 638 break; 639 } 640 } else if (op->common.aml_opcode == AML_DATA_REGION_OP) { 641 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 642 "Executing DataTableRegion Strings Op=%p\n", 643 op)); 644 645 status = 646 acpi_ds_eval_table_region_operands 647 (walk_state, op); 648 if (ACPI_FAILURE(status)) { 649 break; 650 } 651 } else if (op->common.aml_opcode == AML_BANK_FIELD_OP) { 652 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 653 "Executing BankField Op=%p\n", 654 op)); 655 656 status = 657 acpi_ds_eval_bank_field_operands(walk_state, 658 op); 659 if (ACPI_FAILURE(status)) { 660 break; 661 } 662 } 663 break; 664 665 case AML_TYPE_UNDEFINED: 666 667 ACPI_ERROR((AE_INFO, 668 "Undefined opcode type Op=%p", op)); 669 return_ACPI_STATUS(AE_NOT_IMPLEMENTED); 670 671 case AML_TYPE_BOGUS: 672 673 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 674 "Internal opcode=%X type Op=%p\n", 675 walk_state->opcode, op)); 676 break; 677 678 default: 679 680 ACPI_ERROR((AE_INFO, 681 "Unimplemented opcode, class=%X type=%X Opcode=%X Op=%p", 682 op_class, op_type, op->common.aml_opcode, 683 op)); 684 685 status = AE_NOT_IMPLEMENTED; 686 break; 687 } 688 } 689 690 /* 691 * ACPI 2.0 support for 64-bit integers: Truncate numeric 692 * result value if we are executing from a 32-bit ACPI table 693 */ 694 acpi_ex_truncate_for32bit_table(walk_state->result_obj); 695 696 /* 697 * Check if we just completed the evaluation of a 698 * conditional predicate 699 */ 700 if ((ACPI_SUCCESS(status)) && 701 (walk_state->control_state) && 702 (walk_state->control_state->common.state == 703 ACPI_CONTROL_PREDICATE_EXECUTING) && 704 (walk_state->control_state->control.predicate_op == op)) { 705 status = 706 acpi_ds_get_predicate_value(walk_state, 707 walk_state->result_obj); 708 walk_state->result_obj = NULL; 709 } 710 711 cleanup: 712 713 if (walk_state->result_obj) { 714 715 /* Break to debugger to display result */ 716 717 ACPI_DEBUGGER_EXEC(acpi_db_display_result_object 718 (walk_state->result_obj, walk_state)); 719 720 /* 721 * Delete the result op if and only if: 722 * Parent will not use the result -- such as any 723 * non-nested type2 op in a method (parent will be method) 724 */ 725 acpi_ds_delete_result_if_not_used(op, walk_state->result_obj, 726 walk_state); 727 } 728 #ifdef _UNDER_DEVELOPMENT 729 730 if (walk_state->parser_state.aml == walk_state->parser_state.aml_end) { 731 acpi_db_method_end(walk_state); 732 } 733 #endif 734 735 /* Invoke exception handler on error */ 736 737 if (ACPI_FAILURE(status)) { 738 status = acpi_ds_method_error(status, walk_state); 739 } 740 741 /* Always clear the object stack */ 742 743 walk_state->num_operands = 0; 744 return_ACPI_STATUS(status); 745 } 746