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