1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 /****************************************************************************** 3 * 4 * Module Name: psparse - Parser top level AML parse routines 5 * 6 * Copyright (C) 2000 - 2026, Intel Corp. 7 * 8 *****************************************************************************/ 9 10 /* 11 * Parse the AML and build an operation tree as most interpreters, 12 * like Perl, do. Parsing is done by hand rather than with a YACC 13 * generated parser to tightly constrain stack and dynamic memory 14 * usage. At the same time, parsing is kept flexible and the code 15 * fairly compact by parsing based on a list of AML opcode 16 * templates in aml_op_info[] 17 */ 18 19 #include <acpi/acpi.h> 20 #include "accommon.h" 21 #include "acparser.h" 22 #include "acdispat.h" 23 #include "amlcode.h" 24 #include "acinterp.h" 25 #include "acnamesp.h" 26 27 #define _COMPONENT ACPI_PARSER 28 ACPI_MODULE_NAME("psparse") 29 30 /******************************************************************************* 31 * 32 * FUNCTION: acpi_ps_get_opcode_size 33 * 34 * PARAMETERS: opcode - An AML opcode 35 * 36 * RETURN: Size of the opcode, in bytes (1 or 2) 37 * 38 * DESCRIPTION: Get the size of the current opcode. 39 * 40 ******************************************************************************/ 41 u32 acpi_ps_get_opcode_size(u32 opcode) 42 { 43 44 /* Extended (2-byte) opcode if > 255 */ 45 46 if (opcode > 0x00FF) { 47 return (2); 48 } 49 50 /* Otherwise, just a single byte opcode */ 51 52 return (1); 53 } 54 55 /******************************************************************************* 56 * 57 * FUNCTION: acpi_ps_peek_opcode 58 * 59 * PARAMETERS: parser_state - A parser state object 60 * 61 * RETURN: Next AML opcode 62 * 63 * DESCRIPTION: Get next AML opcode (without incrementing AML pointer) 64 * 65 ******************************************************************************/ 66 67 u16 acpi_ps_peek_opcode(struct acpi_parse_state * parser_state) 68 { 69 u8 *aml; 70 u16 opcode; 71 72 aml = parser_state->aml; 73 if (aml >= parser_state->aml_end) { 74 return (0xFFFF); 75 } 76 opcode = (u16) ACPI_GET8(aml); 77 78 if (opcode == AML_EXTENDED_PREFIX) { 79 80 /* Extended opcode, get the second opcode byte */ 81 82 aml++; 83 if (aml >= parser_state->aml_end) { 84 return (0xFFFF); 85 } 86 opcode = (u16) ((opcode << 8) | ACPI_GET8(aml)); 87 } 88 89 return (opcode); 90 } 91 92 /******************************************************************************* 93 * 94 * FUNCTION: acpi_ps_complete_this_op 95 * 96 * PARAMETERS: walk_state - Current State 97 * op - Op to complete 98 * 99 * RETURN: Status 100 * 101 * DESCRIPTION: Perform any cleanup at the completion of an Op. 102 * 103 ******************************************************************************/ 104 105 acpi_status 106 acpi_ps_complete_this_op(struct acpi_walk_state *walk_state, 107 union acpi_parse_object *op) 108 { 109 union acpi_parse_object *prev; 110 union acpi_parse_object *next; 111 const struct acpi_opcode_info *parent_info; 112 union acpi_parse_object *replacement_op = NULL; 113 acpi_status status = AE_OK; 114 115 ACPI_FUNCTION_TRACE_PTR(ps_complete_this_op, op); 116 117 /* Check for null Op, can happen if AML code is corrupt */ 118 119 if (!op) { 120 return_ACPI_STATUS(AE_OK); /* OK for now */ 121 } 122 123 acpi_ex_stop_trace_opcode(op, walk_state); 124 125 /* Delete this op and the subtree below it if asked to */ 126 127 if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) != 128 ACPI_PARSE_DELETE_TREE) 129 || (walk_state->op_info->class == AML_CLASS_ARGUMENT)) { 130 return_ACPI_STATUS(AE_OK); 131 } 132 133 /* Make sure that we only delete this subtree */ 134 135 if (op->common.parent) { 136 prev = op->common.parent->common.value.arg; 137 if (!prev) { 138 139 /* Nothing more to do */ 140 141 goto cleanup; 142 } 143 144 /* 145 * Check if we need to replace the operator and its subtree 146 * with a return value op (placeholder op) 147 */ 148 parent_info = 149 acpi_ps_get_opcode_info(op->common.parent->common. 150 aml_opcode); 151 152 switch (parent_info->class) { 153 case AML_CLASS_CONTROL: 154 155 break; 156 157 case AML_CLASS_CREATE: 158 /* 159 * These opcodes contain term_arg operands. The current 160 * op must be replaced by a placeholder return op 161 */ 162 replacement_op = 163 acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP, 164 op->common.aml); 165 if (!replacement_op) { 166 status = AE_NO_MEMORY; 167 } 168 break; 169 170 case AML_CLASS_NAMED_OBJECT: 171 /* 172 * These opcodes contain term_arg operands. The current 173 * op must be replaced by a placeholder return op 174 */ 175 if ((op->common.parent->common.aml_opcode == 176 AML_REGION_OP) 177 || (op->common.parent->common.aml_opcode == 178 AML_DATA_REGION_OP) 179 || (op->common.parent->common.aml_opcode == 180 AML_BUFFER_OP) 181 || (op->common.parent->common.aml_opcode == 182 AML_PACKAGE_OP) 183 || (op->common.parent->common.aml_opcode == 184 AML_BANK_FIELD_OP) 185 || (op->common.parent->common.aml_opcode == 186 AML_VARIABLE_PACKAGE_OP)) { 187 replacement_op = 188 acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP, 189 op->common.aml); 190 if (!replacement_op) { 191 status = AE_NO_MEMORY; 192 } 193 } else 194 if ((op->common.parent->common.aml_opcode == 195 AML_NAME_OP) 196 && (walk_state->pass_number <= 197 ACPI_IMODE_LOAD_PASS2)) { 198 if ((op->common.aml_opcode == AML_BUFFER_OP) 199 || (op->common.aml_opcode == AML_PACKAGE_OP) 200 || (op->common.aml_opcode == 201 AML_VARIABLE_PACKAGE_OP)) { 202 replacement_op = 203 acpi_ps_alloc_op(op->common. 204 aml_opcode, 205 op->common.aml); 206 if (!replacement_op) { 207 status = AE_NO_MEMORY; 208 } else { 209 replacement_op->named.data = 210 op->named.data; 211 replacement_op->named.length = 212 op->named.length; 213 } 214 } 215 } 216 break; 217 218 default: 219 220 replacement_op = 221 acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP, 222 op->common.aml); 223 if (!replacement_op) { 224 status = AE_NO_MEMORY; 225 } 226 } 227 228 /* We must unlink this op from the parent tree */ 229 230 if (prev == op) { 231 232 /* This op is the first in the list */ 233 234 if (replacement_op) { 235 replacement_op->common.parent = 236 op->common.parent; 237 replacement_op->common.value.arg = NULL; 238 replacement_op->common.node = op->common.node; 239 op->common.parent->common.value.arg = 240 replacement_op; 241 replacement_op->common.next = op->common.next; 242 } else { 243 op->common.parent->common.value.arg = 244 op->common.next; 245 } 246 } 247 248 /* Search the parent list */ 249 250 else 251 while (prev) { 252 253 /* Traverse all siblings in the parent's argument list */ 254 255 next = prev->common.next; 256 if (next == op) { 257 if (replacement_op) { 258 replacement_op->common.parent = 259 op->common.parent; 260 replacement_op->common.value. 261 arg = NULL; 262 replacement_op->common.node = 263 op->common.node; 264 prev->common.next = 265 replacement_op; 266 replacement_op->common.next = 267 op->common.next; 268 next = NULL; 269 } else { 270 prev->common.next = 271 op->common.next; 272 next = NULL; 273 } 274 } 275 prev = next; 276 } 277 } 278 279 cleanup: 280 281 /* Now we can actually delete the subtree rooted at Op */ 282 283 acpi_ps_delete_parse_tree(op); 284 return_ACPI_STATUS(status); 285 } 286 287 /******************************************************************************* 288 * 289 * FUNCTION: acpi_ps_next_parse_state 290 * 291 * PARAMETERS: walk_state - Current state 292 * op - Current parse op 293 * callback_status - Status from previous operation 294 * 295 * RETURN: Status 296 * 297 * DESCRIPTION: Update the parser state based upon the return exception from 298 * the parser callback. 299 * 300 ******************************************************************************/ 301 302 acpi_status 303 acpi_ps_next_parse_state(struct acpi_walk_state *walk_state, 304 union acpi_parse_object *op, 305 acpi_status callback_status) 306 { 307 struct acpi_parse_state *parser_state = &walk_state->parser_state; 308 acpi_status status = AE_CTRL_PENDING; 309 u8 *aml; 310 311 ACPI_FUNCTION_TRACE_PTR(ps_next_parse_state, op); 312 313 switch (callback_status) { 314 case AE_CTRL_TERMINATE: 315 /* 316 * A control method was terminated via a RETURN statement. 317 * The walk of this method is complete. 318 */ 319 parser_state->aml = parser_state->aml_end; 320 status = AE_CTRL_TERMINATE; 321 break; 322 323 case AE_CTRL_BREAK: 324 325 parser_state->aml = walk_state->aml_last_while; 326 walk_state->control_state->common.value = FALSE; 327 status = AE_CTRL_BREAK; 328 break; 329 330 case AE_CTRL_CONTINUE: 331 332 parser_state->aml = walk_state->aml_last_while; 333 status = AE_CTRL_CONTINUE; 334 break; 335 336 case AE_CTRL_PENDING: 337 338 parser_state->aml = walk_state->aml_last_while; 339 break; 340 341 #if 0 342 case AE_CTRL_SKIP: 343 344 parser_state->aml = parser_state->scope->parse_scope.pkg_end; 345 status = AE_OK; 346 break; 347 #endif 348 349 case AE_CTRL_TRUE: 350 /* 351 * Predicate of an IF was true, and we are at the matching ELSE. 352 * Just close out this package 353 */ 354 aml = parser_state->aml; 355 356 parser_state->aml = acpi_ps_get_next_package_end(parser_state); 357 if ((parser_state->aml > parser_state->aml_end) || 358 (parser_state->aml < aml)) { 359 status = AE_AML_PACKAGE_LIMIT; 360 break; 361 } 362 status = AE_CTRL_PENDING; 363 break; 364 365 case AE_CTRL_FALSE: 366 /* 367 * Either an IF/WHILE Predicate was false or we encountered a BREAK 368 * opcode. In both cases, we do not execute the rest of the 369 * package; We simply close out the parent (finishing the walk of 370 * this branch of the tree) and continue execution at the parent 371 * level. 372 */ 373 parser_state->aml = parser_state->scope->parse_scope.pkg_end; 374 375 /* In the case of a BREAK, just force a predicate (if any) to FALSE */ 376 377 walk_state->control_state->common.value = FALSE; 378 status = AE_CTRL_END; 379 break; 380 381 case AE_CTRL_TRANSFER: 382 383 /* A method call (invocation) -- transfer control */ 384 385 status = AE_CTRL_TRANSFER; 386 walk_state->prev_op = op; 387 walk_state->method_call_op = op; 388 walk_state->method_call_node = 389 (op->common.value.arg)->common.node; 390 391 /* Will return value (if any) be used by the caller? */ 392 393 walk_state->return_used = 394 acpi_ds_is_result_used(op, walk_state); 395 break; 396 397 default: 398 399 status = callback_status; 400 if (ACPI_CNTL_EXCEPTION(callback_status)) { 401 status = AE_OK; 402 } 403 break; 404 } 405 406 return_ACPI_STATUS(status); 407 } 408 409 /******************************************************************************* 410 * 411 * FUNCTION: acpi_ps_parse_aml 412 * 413 * PARAMETERS: walk_state - Current state 414 * 415 * 416 * RETURN: Status 417 * 418 * DESCRIPTION: Parse raw AML and return a tree of ops 419 * 420 ******************************************************************************/ 421 422 acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) 423 { 424 acpi_status status; 425 struct acpi_thread_state *thread; 426 struct acpi_thread_state *prev_walk_list = acpi_gbl_current_walk_list; 427 struct acpi_walk_state *previous_walk_state; 428 429 ACPI_FUNCTION_TRACE(ps_parse_aml); 430 431 ACPI_DEBUG_PRINT((ACPI_DB_PARSE, 432 "Entered with WalkState=%p Aml=%p size=%X\n", 433 walk_state, walk_state->parser_state.aml, 434 walk_state->parser_state.aml_size)); 435 436 if (!walk_state->parser_state.aml) { 437 return_ACPI_STATUS(AE_BAD_ADDRESS); 438 } 439 440 /* Create and initialize a new thread state */ 441 442 thread = acpi_ut_create_thread_state(); 443 if (!thread) { 444 if (walk_state->method_desc) { 445 446 /* Executing a control method - additional cleanup */ 447 448 acpi_ds_terminate_control_method(walk_state-> 449 method_desc, 450 walk_state); 451 } 452 453 acpi_ds_delete_walk_state(walk_state); 454 return_ACPI_STATUS(AE_NO_MEMORY); 455 } 456 457 walk_state->thread = thread; 458 459 /* 460 * If executing a method, the starting sync_level is this method's 461 * sync_level 462 */ 463 if (walk_state->method_desc) { 464 walk_state->thread->current_sync_level = 465 walk_state->method_desc->method.sync_level; 466 } 467 468 acpi_ds_push_walk_state(walk_state, thread); 469 470 /* 471 * This global allows the AML debugger to get a handle to the currently 472 * executing control method. 473 */ 474 acpi_gbl_current_walk_list = thread; 475 476 /* 477 * Execute the walk loop as long as there is a valid Walk State. This 478 * handles nested control method invocations without recursion. 479 */ 480 ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "State=%p\n", walk_state)); 481 482 status = AE_OK; 483 while (walk_state) { 484 if (ACPI_SUCCESS(status)) { 485 /* 486 * The parse_loop executes AML until the method terminates 487 * or calls another method. 488 */ 489 status = acpi_ps_parse_loop(walk_state); 490 } 491 492 ACPI_DEBUG_PRINT((ACPI_DB_PARSE, 493 "Completed one call to walk loop, %s State=%p\n", 494 acpi_format_exception(status), walk_state)); 495 496 if (walk_state->method_pathname && walk_state->method_is_nested) { 497 498 /* Optional object evaluation log */ 499 500 ACPI_DEBUG_PRINT_RAW((ACPI_DB_EVALUATION, 501 "%-26s: %*s%s\n", 502 " Exit nested method", 503 (walk_state-> 504 method_nesting_depth + 1) * 3, 505 " ", 506 &walk_state->method_pathname[1])); 507 508 ACPI_FREE(walk_state->method_pathname); 509 walk_state->method_is_nested = FALSE; 510 } 511 if (status == AE_CTRL_TRANSFER) { 512 /* 513 * A method call was detected. 514 * Transfer control to the called control method 515 */ 516 status = 517 acpi_ds_call_control_method(thread, walk_state, 518 NULL); 519 if (ACPI_FAILURE(status)) { 520 status = 521 acpi_ds_method_error(status, walk_state); 522 } 523 524 /* 525 * If the transfer to the new method method call worked, 526 * a new walk state was created -- get it 527 */ 528 walk_state = acpi_ds_get_current_walk_state(thread); 529 continue; 530 } else if (status == AE_CTRL_TERMINATE) { 531 status = AE_OK; 532 } else if ((status != AE_OK) && (walk_state->method_desc)) { 533 534 /* Either the method parse or actual execution failed */ 535 536 acpi_ex_exit_interpreter(); 537 if (status == AE_ABORT_METHOD) { 538 acpi_ns_print_node_pathname(walk_state-> 539 method_node, 540 "Aborting method"); 541 acpi_os_printf("\n"); 542 } else { 543 ACPI_ERROR_METHOD("Aborting method", 544 walk_state->method_node, NULL, 545 status); 546 } 547 acpi_ex_enter_interpreter(); 548 549 /* Check for possible multi-thread reentrancy problem */ 550 551 if ((status == AE_ALREADY_EXISTS) && 552 (!(walk_state->method_desc->method.info_flags & 553 ACPI_METHOD_SERIALIZED))) { 554 /* 555 * Method is not serialized and tried to create an object 556 * twice. The probable cause is that the method cannot 557 * handle reentrancy. Mark as "pending serialized" now, and 558 * then mark "serialized" when the last thread exits. 559 */ 560 walk_state->method_desc->method.info_flags |= 561 ACPI_METHOD_SERIALIZED_PENDING; 562 } 563 } 564 565 /* We are done with this walk, move on to the parent if any */ 566 567 walk_state = acpi_ds_pop_walk_state(thread); 568 569 /* Reset the current scope to the beginning of scope stack */ 570 571 acpi_ds_scope_stack_clear(walk_state); 572 573 /* 574 * If we just returned from the execution of a control method or if we 575 * encountered an error during the method parse phase, there's lots of 576 * cleanup to do 577 */ 578 if (((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == 579 ACPI_PARSE_EXECUTE && 580 !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) || 581 (ACPI_FAILURE(status))) { 582 acpi_ds_terminate_control_method(walk_state-> 583 method_desc, 584 walk_state); 585 } 586 587 /* Delete this walk state and all linked control states */ 588 589 acpi_ps_cleanup_scope(&walk_state->parser_state); 590 previous_walk_state = walk_state; 591 592 ACPI_DEBUG_PRINT((ACPI_DB_PARSE, 593 "ReturnValue=%p, ImplicitValue=%p State=%p\n", 594 walk_state->return_desc, 595 walk_state->implicit_return_obj, walk_state)); 596 597 /* Check if we have restarted a preempted walk */ 598 599 walk_state = acpi_ds_get_current_walk_state(thread); 600 if (walk_state) { 601 if (ACPI_SUCCESS(status)) { 602 /* 603 * There is another walk state, restart it. 604 * If the method return value is not used by the parent, 605 * The object is deleted 606 */ 607 if (!previous_walk_state->return_desc) { 608 /* 609 * In slack mode execution, if there is no return value 610 * we should implicitly return zero (0) as a default value. 611 */ 612 if (acpi_gbl_enable_interpreter_slack && 613 !previous_walk_state-> 614 implicit_return_obj) { 615 previous_walk_state-> 616 implicit_return_obj = 617 acpi_ut_create_integer_object 618 ((u64) 0); 619 if (!previous_walk_state-> 620 implicit_return_obj) { 621 return_ACPI_STATUS 622 (AE_NO_MEMORY); 623 } 624 } 625 626 /* Restart the calling control method */ 627 628 status = 629 acpi_ds_restart_control_method 630 (walk_state, 631 previous_walk_state-> 632 implicit_return_obj); 633 } else { 634 /* 635 * We have a valid return value, delete any implicit 636 * return value. 637 */ 638 acpi_ds_clear_implicit_return 639 (previous_walk_state); 640 641 status = 642 acpi_ds_restart_control_method 643 (walk_state, 644 previous_walk_state->return_desc); 645 } 646 if (ACPI_SUCCESS(status)) { 647 walk_state->walk_type |= 648 ACPI_WALK_METHOD_RESTART; 649 } 650 } else { 651 /* On error, delete any return object or implicit return */ 652 653 acpi_ut_remove_reference(previous_walk_state-> 654 return_desc); 655 acpi_ds_clear_implicit_return 656 (previous_walk_state); 657 } 658 } 659 660 /* 661 * Just completed a 1st-level method, save the final internal return 662 * value (if any) 663 */ 664 else if (previous_walk_state->caller_return_desc) { 665 if (previous_walk_state->implicit_return_obj) { 666 *(previous_walk_state->caller_return_desc) = 667 previous_walk_state->implicit_return_obj; 668 } else { 669 /* NULL if no return value */ 670 671 *(previous_walk_state->caller_return_desc) = 672 previous_walk_state->return_desc; 673 } 674 } else { 675 if (previous_walk_state->return_desc) { 676 677 /* Caller doesn't want it, must delete it */ 678 679 acpi_ut_remove_reference(previous_walk_state-> 680 return_desc); 681 } 682 if (previous_walk_state->implicit_return_obj) { 683 684 /* Caller doesn't want it, must delete it */ 685 686 acpi_ut_remove_reference(previous_walk_state-> 687 implicit_return_obj); 688 } 689 } 690 691 acpi_ds_delete_walk_state(previous_walk_state); 692 } 693 694 /* Normal exit */ 695 696 acpi_ex_release_all_mutexes(thread); 697 acpi_ut_delete_generic_state(ACPI_CAST_PTR 698 (union acpi_generic_state, thread)); 699 acpi_gbl_current_walk_list = prev_walk_list; 700 return_ACPI_STATUS(status); 701 } 702