at v2.6.13-rc6 1304 lines 35 kB view raw
1/****************************************************************************** 2 * 3 * Module Name: psparse - Parser top level AML parse routines 4 * 5 *****************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2005, R. Byron Moore 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 45/* 46 * Parse the AML and build an operation tree as most interpreters, 47 * like Perl, do. Parsing is done by hand rather than with a YACC 48 * generated parser to tightly constrain stack and dynamic memory 49 * usage. At the same time, parsing is kept flexible and the code 50 * fairly compact by parsing based on a list of AML opcode 51 * templates in aml_op_info[] 52 */ 53 54#include <acpi/acpi.h> 55#include <acpi/acparser.h> 56#include <acpi/acdispat.h> 57#include <acpi/amlcode.h> 58#include <acpi/acnamesp.h> 59#include <acpi/acinterp.h> 60 61#define _COMPONENT ACPI_PARSER 62 ACPI_MODULE_NAME ("psparse") 63 64 65static u32 acpi_gbl_depth = 0; 66 67/* Local prototypes */ 68 69static void 70acpi_ps_complete_this_op ( 71 struct acpi_walk_state *walk_state, 72 union acpi_parse_object *op); 73 74static acpi_status 75acpi_ps_next_parse_state ( 76 struct acpi_walk_state *walk_state, 77 union acpi_parse_object *op, 78 acpi_status callback_status); 79 80static acpi_status 81acpi_ps_parse_loop ( 82 struct acpi_walk_state *walk_state); 83 84 85/******************************************************************************* 86 * 87 * FUNCTION: acpi_ps_get_opcode_size 88 * 89 * PARAMETERS: Opcode - An AML opcode 90 * 91 * RETURN: Size of the opcode, in bytes (1 or 2) 92 * 93 * DESCRIPTION: Get the size of the current opcode. 94 * 95 ******************************************************************************/ 96 97u32 98acpi_ps_get_opcode_size ( 99 u32 opcode) 100{ 101 102 /* Extended (2-byte) opcode if > 255 */ 103 104 if (opcode > 0x00FF) { 105 return (2); 106 } 107 108 /* Otherwise, just a single byte opcode */ 109 110 return (1); 111} 112 113 114/******************************************************************************* 115 * 116 * FUNCTION: acpi_ps_peek_opcode 117 * 118 * PARAMETERS: parser_state - A parser state object 119 * 120 * RETURN: Next AML opcode 121 * 122 * DESCRIPTION: Get next AML opcode (without incrementing AML pointer) 123 * 124 ******************************************************************************/ 125 126u16 127acpi_ps_peek_opcode ( 128 struct acpi_parse_state *parser_state) 129{ 130 u8 *aml; 131 u16 opcode; 132 133 134 aml = parser_state->aml; 135 opcode = (u16) ACPI_GET8 (aml); 136 137 if (opcode == AML_EXTOP) { 138 /* Extended opcode */ 139 140 aml++; 141 opcode = (u16) ((opcode << 8) | ACPI_GET8 (aml)); 142 } 143 144 return (opcode); 145} 146 147 148/******************************************************************************* 149 * 150 * FUNCTION: acpi_ps_complete_this_op 151 * 152 * PARAMETERS: walk_state - Current State 153 * Op - Op to complete 154 * 155 * RETURN: None. 156 * 157 * DESCRIPTION: Perform any cleanup at the completion of an Op. 158 * 159 ******************************************************************************/ 160 161static void 162acpi_ps_complete_this_op ( 163 struct acpi_walk_state *walk_state, 164 union acpi_parse_object *op) 165{ 166 union acpi_parse_object *prev; 167 union acpi_parse_object *next; 168 const struct acpi_opcode_info *parent_info; 169 union acpi_parse_object *replacement_op = NULL; 170 171 172 ACPI_FUNCTION_TRACE_PTR ("ps_complete_this_op", op); 173 174 175 /* Check for null Op, can happen if AML code is corrupt */ 176 177 if (!op) { 178 return_VOID; 179 } 180 181 /* Delete this op and the subtree below it if asked to */ 182 183 if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) != ACPI_PARSE_DELETE_TREE) || 184 (walk_state->op_info->class == AML_CLASS_ARGUMENT)) { 185 return_VOID; 186 } 187 188 /* Make sure that we only delete this subtree */ 189 190 if (op->common.parent) { 191 /* 192 * Check if we need to replace the operator and its subtree 193 * with a return value op (placeholder op) 194 */ 195 parent_info = acpi_ps_get_opcode_info (op->common.parent->common.aml_opcode); 196 197 switch (parent_info->class) { 198 case AML_CLASS_CONTROL: 199 break; 200 201 case AML_CLASS_CREATE: 202 203 /* 204 * These opcodes contain term_arg operands. The current 205 * op must be replaced by a placeholder return op 206 */ 207 replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP); 208 if (!replacement_op) { 209 goto cleanup; 210 } 211 break; 212 213 case AML_CLASS_NAMED_OBJECT: 214 215 /* 216 * These opcodes contain term_arg operands. The current 217 * op must be replaced by a placeholder return op 218 */ 219 if ((op->common.parent->common.aml_opcode == AML_REGION_OP) || 220 (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP) || 221 (op->common.parent->common.aml_opcode == AML_BUFFER_OP) || 222 (op->common.parent->common.aml_opcode == AML_PACKAGE_OP) || 223 (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) { 224 replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP); 225 if (!replacement_op) { 226 goto cleanup; 227 } 228 } 229 230 if ((op->common.parent->common.aml_opcode == AML_NAME_OP) && 231 (walk_state->descending_callback != acpi_ds_exec_begin_op)) { 232 if ((op->common.aml_opcode == AML_BUFFER_OP) || 233 (op->common.aml_opcode == AML_PACKAGE_OP) || 234 (op->common.aml_opcode == AML_VAR_PACKAGE_OP)) { 235 replacement_op = acpi_ps_alloc_op (op->common.aml_opcode); 236 if (!replacement_op) { 237 goto cleanup; 238 } 239 240 replacement_op->named.data = op->named.data; 241 replacement_op->named.length = op->named.length; 242 } 243 } 244 break; 245 246 default: 247 replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP); 248 if (!replacement_op) { 249 goto cleanup; 250 } 251 } 252 253 /* We must unlink this op from the parent tree */ 254 255 prev = op->common.parent->common.value.arg; 256 if (prev == op) { 257 /* This op is the first in the list */ 258 259 if (replacement_op) { 260 replacement_op->common.parent = op->common.parent; 261 replacement_op->common.value.arg = NULL; 262 replacement_op->common.node = op->common.node; 263 op->common.parent->common.value.arg = replacement_op; 264 replacement_op->common.next = op->common.next; 265 } 266 else { 267 op->common.parent->common.value.arg = op->common.next; 268 } 269 } 270 271 /* Search the parent list */ 272 273 else while (prev) { 274 /* Traverse all siblings in the parent's argument list */ 275 276 next = prev->common.next; 277 if (next == op) { 278 if (replacement_op) { 279 replacement_op->common.parent = op->common.parent; 280 replacement_op->common.value.arg = NULL; 281 replacement_op->common.node = op->common.node; 282 prev->common.next = replacement_op; 283 replacement_op->common.next = op->common.next; 284 next = NULL; 285 } 286 else { 287 prev->common.next = op->common.next; 288 next = NULL; 289 } 290 } 291 prev = next; 292 } 293 } 294 295 296cleanup: 297 298 /* Now we can actually delete the subtree rooted at Op */ 299 300 acpi_ps_delete_parse_tree (op); 301 return_VOID; 302} 303 304 305/******************************************************************************* 306 * 307 * FUNCTION: acpi_ps_next_parse_state 308 * 309 * PARAMETERS: walk_state - Current state 310 * Op - Current parse op 311 * callback_status - Status from previous operation 312 * 313 * RETURN: Status 314 * 315 * DESCRIPTION: Update the parser state based upon the return exception from 316 * the parser callback. 317 * 318 ******************************************************************************/ 319 320static acpi_status 321acpi_ps_next_parse_state ( 322 struct acpi_walk_state *walk_state, 323 union acpi_parse_object *op, 324 acpi_status callback_status) 325{ 326 struct acpi_parse_state *parser_state = &walk_state->parser_state; 327 acpi_status status = AE_CTRL_PENDING; 328 329 330 ACPI_FUNCTION_TRACE_PTR ("ps_next_parse_state", op); 331 332 333 switch (callback_status) { 334 case AE_CTRL_TERMINATE: 335 336 /* 337 * A control method was terminated via a RETURN statement. 338 * The walk of this method is complete. 339 */ 340 parser_state->aml = parser_state->aml_end; 341 status = AE_CTRL_TERMINATE; 342 break; 343 344 345 case AE_CTRL_BREAK: 346 347 parser_state->aml = walk_state->aml_last_while; 348 walk_state->control_state->common.value = FALSE; 349 status = AE_CTRL_BREAK; 350 break; 351 352 case AE_CTRL_CONTINUE: 353 354 355 parser_state->aml = walk_state->aml_last_while; 356 status = AE_CTRL_CONTINUE; 357 break; 358 359 case AE_CTRL_PENDING: 360 361 parser_state->aml = walk_state->aml_last_while; 362 break; 363 364#if 0 365 case AE_CTRL_SKIP: 366 367 parser_state->aml = parser_state->scope->parse_scope.pkg_end; 368 status = AE_OK; 369 break; 370#endif 371 372 case AE_CTRL_TRUE: 373 374 /* 375 * Predicate of an IF was true, and we are at the matching ELSE. 376 * Just close out this package 377 */ 378 parser_state->aml = acpi_ps_get_next_package_end (parser_state); 379 break; 380 381 382 case AE_CTRL_FALSE: 383 384 /* 385 * Either an IF/WHILE Predicate was false or we encountered a BREAK 386 * opcode. In both cases, we do not execute the rest of the 387 * package; We simply close out the parent (finishing the walk of 388 * this branch of the tree) and continue execution at the parent 389 * level. 390 */ 391 parser_state->aml = parser_state->scope->parse_scope.pkg_end; 392 393 /* In the case of a BREAK, just force a predicate (if any) to FALSE */ 394 395 walk_state->control_state->common.value = FALSE; 396 status = AE_CTRL_END; 397 break; 398 399 400 case AE_CTRL_TRANSFER: 401 402 /* A method call (invocation) -- transfer control */ 403 404 status = AE_CTRL_TRANSFER; 405 walk_state->prev_op = op; 406 walk_state->method_call_op = op; 407 walk_state->method_call_node = (op->common.value.arg)->common.node; 408 409 /* Will return value (if any) be used by the caller? */ 410 411 walk_state->return_used = acpi_ds_is_result_used (op, walk_state); 412 break; 413 414 415 default: 416 417 status = callback_status; 418 if ((callback_status & AE_CODE_MASK) == AE_CODE_CONTROL) { 419 status = AE_OK; 420 } 421 break; 422 } 423 424 return_ACPI_STATUS (status); 425} 426 427 428/******************************************************************************* 429 * 430 * FUNCTION: acpi_ps_parse_loop 431 * 432 * PARAMETERS: walk_state - Current state 433 * 434 * RETURN: Status 435 * 436 * DESCRIPTION: Parse AML (pointed to by the current parser state) and return 437 * a tree of ops. 438 * 439 ******************************************************************************/ 440 441static acpi_status 442acpi_ps_parse_loop ( 443 struct acpi_walk_state *walk_state) 444{ 445 acpi_status status = AE_OK; 446 union acpi_parse_object *op = NULL; /* current op */ 447 union acpi_parse_object *arg = NULL; 448 union acpi_parse_object *pre_op = NULL; 449 struct acpi_parse_state *parser_state; 450 u8 *aml_op_start = NULL; 451 452 453 ACPI_FUNCTION_TRACE_PTR ("ps_parse_loop", walk_state); 454 455 if (walk_state->descending_callback == NULL) { 456 return_ACPI_STATUS (AE_BAD_PARAMETER); 457 } 458 459 parser_state = &walk_state->parser_state; 460 walk_state->arg_types = 0; 461 462#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) 463 464 if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) { 465 /* We are restarting a preempted control method */ 466 467 if (acpi_ps_has_completed_scope (parser_state)) { 468 /* 469 * We must check if a predicate to an IF or WHILE statement 470 * was just completed 471 */ 472 if ((parser_state->scope->parse_scope.op) && 473 ((parser_state->scope->parse_scope.op->common.aml_opcode == AML_IF_OP) || 474 (parser_state->scope->parse_scope.op->common.aml_opcode == AML_WHILE_OP)) && 475 (walk_state->control_state) && 476 (walk_state->control_state->common.state == 477 ACPI_CONTROL_PREDICATE_EXECUTING)) { 478 /* 479 * A predicate was just completed, get the value of the 480 * predicate and branch based on that value 481 */ 482 walk_state->op = NULL; 483 status = acpi_ds_get_predicate_value (walk_state, ACPI_TO_POINTER (TRUE)); 484 if (ACPI_FAILURE (status) && 485 ((status & AE_CODE_MASK) != AE_CODE_CONTROL)) { 486 if (status == AE_AML_NO_RETURN_VALUE) { 487 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 488 "Invoked method did not return a value, %s\n", 489 acpi_format_exception (status))); 490 491 } 492 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 493 "get_predicate Failed, %s\n", 494 acpi_format_exception (status))); 495 return_ACPI_STATUS (status); 496 } 497 498 status = acpi_ps_next_parse_state (walk_state, op, status); 499 } 500 501 acpi_ps_pop_scope (parser_state, &op, 502 &walk_state->arg_types, &walk_state->arg_count); 503 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", op)); 504 } 505 else if (walk_state->prev_op) { 506 /* We were in the middle of an op */ 507 508 op = walk_state->prev_op; 509 walk_state->arg_types = walk_state->prev_arg_types; 510 } 511 } 512#endif 513 514 /* Iterative parsing loop, while there is more AML to process: */ 515 516 while ((parser_state->aml < parser_state->aml_end) || (op)) { 517 aml_op_start = parser_state->aml; 518 if (!op) { 519 /* Get the next opcode from the AML stream */ 520 521 walk_state->aml_offset = (u32) ACPI_PTR_DIFF (parser_state->aml, 522 parser_state->aml_start); 523 walk_state->opcode = acpi_ps_peek_opcode (parser_state); 524 525 /* 526 * First cut to determine what we have found: 527 * 1) A valid AML opcode 528 * 2) A name string 529 * 3) An unknown/invalid opcode 530 */ 531 walk_state->op_info = acpi_ps_get_opcode_info (walk_state->opcode); 532 switch (walk_state->op_info->class) { 533 case AML_CLASS_ASCII: 534 case AML_CLASS_PREFIX: 535 /* 536 * Starts with a valid prefix or ASCII char, this is a name 537 * string. Convert the bare name string to a namepath. 538 */ 539 walk_state->opcode = AML_INT_NAMEPATH_OP; 540 walk_state->arg_types = ARGP_NAMESTRING; 541 break; 542 543 case AML_CLASS_UNKNOWN: 544 545 /* The opcode is unrecognized. Just skip unknown opcodes */ 546 547 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 548 "Found unknown opcode %X at AML address %p offset %X, ignoring\n", 549 walk_state->opcode, parser_state->aml, walk_state->aml_offset)); 550 551 ACPI_DUMP_BUFFER (parser_state->aml, 128); 552 553 /* Assume one-byte bad opcode */ 554 555 parser_state->aml++; 556 continue; 557 558 default: 559 560 /* Found opcode info, this is a normal opcode */ 561 562 parser_state->aml += acpi_ps_get_opcode_size (walk_state->opcode); 563 walk_state->arg_types = walk_state->op_info->parse_args; 564 break; 565 } 566 567 /* Create Op structure and append to parent's argument list */ 568 569 if (walk_state->op_info->flags & AML_NAMED) { 570 /* Allocate a new pre_op if necessary */ 571 572 if (!pre_op) { 573 pre_op = acpi_ps_alloc_op (walk_state->opcode); 574 if (!pre_op) { 575 status = AE_NO_MEMORY; 576 goto close_this_op; 577 } 578 } 579 580 pre_op->common.value.arg = NULL; 581 pre_op->common.aml_opcode = walk_state->opcode; 582 583 /* 584 * Get and append arguments until we find the node that contains 585 * the name (the type ARGP_NAME). 586 */ 587 while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) && 588 (GET_CURRENT_ARG_TYPE (walk_state->arg_types) != ARGP_NAME)) { 589 status = acpi_ps_get_next_arg (walk_state, parser_state, 590 GET_CURRENT_ARG_TYPE (walk_state->arg_types), &arg); 591 if (ACPI_FAILURE (status)) { 592 goto close_this_op; 593 } 594 595 acpi_ps_append_arg (pre_op, arg); 596 INCREMENT_ARG_LIST (walk_state->arg_types); 597 } 598 599 /* 600 * Make sure that we found a NAME and didn't run out of 601 * arguments 602 */ 603 if (!GET_CURRENT_ARG_TYPE (walk_state->arg_types)) { 604 status = AE_AML_NO_OPERAND; 605 goto close_this_op; 606 } 607 608 /* We know that this arg is a name, move to next arg */ 609 610 INCREMENT_ARG_LIST (walk_state->arg_types); 611 612 /* 613 * Find the object. This will either insert the object into 614 * the namespace or simply look it up 615 */ 616 walk_state->op = NULL; 617 618 status = walk_state->descending_callback (walk_state, &op); 619 if (ACPI_FAILURE (status)) { 620 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 621 "During name lookup/catalog, %s\n", 622 acpi_format_exception (status))); 623 goto close_this_op; 624 } 625 626 if (!op) { 627 continue; 628 } 629 630 status = acpi_ps_next_parse_state (walk_state, op, status); 631 if (status == AE_CTRL_PENDING) { 632 status = AE_OK; 633 goto close_this_op; 634 } 635 636 if (ACPI_FAILURE (status)) { 637 goto close_this_op; 638 } 639 640 acpi_ps_append_arg (op, pre_op->common.value.arg); 641 acpi_gbl_depth++; 642 643 if (op->common.aml_opcode == AML_REGION_OP) { 644 /* 645 * Defer final parsing of an operation_region body, 646 * because we don't have enough info in the first pass 647 * to parse it correctly (i.e., there may be method 648 * calls within the term_arg elements of the body.) 649 * 650 * However, we must continue parsing because 651 * the opregion is not a standalone package -- 652 * we don't know where the end is at this point. 653 * 654 * (Length is unknown until parse of the body complete) 655 */ 656 op->named.data = aml_op_start; 657 op->named.length = 0; 658 } 659 } 660 else { 661 /* Not a named opcode, just allocate Op and append to parent */ 662 663 walk_state->op_info = acpi_ps_get_opcode_info (walk_state->opcode); 664 op = acpi_ps_alloc_op (walk_state->opcode); 665 if (!op) { 666 status = AE_NO_MEMORY; 667 goto close_this_op; 668 } 669 670 if (walk_state->op_info->flags & AML_CREATE) { 671 /* 672 * Backup to beginning of create_xXXfield declaration 673 * body_length is unknown until we parse the body 674 */ 675 op->named.data = aml_op_start; 676 op->named.length = 0; 677 } 678 679 acpi_ps_append_arg (acpi_ps_get_parent_scope (parser_state), op); 680 681 if ((walk_state->descending_callback != NULL)) { 682 /* 683 * Find the object. This will either insert the object into 684 * the namespace or simply look it up 685 */ 686 walk_state->op = op; 687 688 status = walk_state->descending_callback (walk_state, &op); 689 status = acpi_ps_next_parse_state (walk_state, op, status); 690 if (status == AE_CTRL_PENDING) { 691 status = AE_OK; 692 goto close_this_op; 693 } 694 695 if (ACPI_FAILURE (status)) { 696 goto close_this_op; 697 } 698 } 699 } 700 701 op->common.aml_offset = walk_state->aml_offset; 702 703 if (walk_state->op_info) { 704 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, 705 "Opcode %4.4X [%s] Op %p Aml %p aml_offset %5.5X\n", 706 (u32) op->common.aml_opcode, walk_state->op_info->name, 707 op, parser_state->aml, op->common.aml_offset)); 708 } 709 } 710 711 712 /* 713 * Start arg_count at zero because we don't know if there are 714 * any args yet 715 */ 716 walk_state->arg_count = 0; 717 718 /* Are there any arguments that must be processed? */ 719 720 if (walk_state->arg_types) { 721 /* Get arguments */ 722 723 switch (op->common.aml_opcode) { 724 case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ 725 case AML_WORD_OP: /* AML_WORDDATA_ARG */ 726 case AML_DWORD_OP: /* AML_DWORDATA_ARG */ 727 case AML_QWORD_OP: /* AML_QWORDATA_ARG */ 728 case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */ 729 730 /* Fill in constant or string argument directly */ 731 732 acpi_ps_get_next_simple_arg (parser_state, 733 GET_CURRENT_ARG_TYPE (walk_state->arg_types), op); 734 break; 735 736 case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */ 737 738 status = acpi_ps_get_next_namepath (walk_state, parser_state, op, 1); 739 if (ACPI_FAILURE (status)) { 740 goto close_this_op; 741 } 742 743 walk_state->arg_types = 0; 744 break; 745 746 default: 747 748 /* 749 * Op is not a constant or string, append each argument 750 * to the Op 751 */ 752 while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) && 753 !walk_state->arg_count) { 754 walk_state->aml_offset = (u32) 755 ACPI_PTR_DIFF (parser_state->aml, parser_state->aml_start); 756 757 status = acpi_ps_get_next_arg (walk_state, parser_state, 758 GET_CURRENT_ARG_TYPE (walk_state->arg_types), 759 &arg); 760 if (ACPI_FAILURE (status)) { 761 goto close_this_op; 762 } 763 764 if (arg) { 765 arg->common.aml_offset = walk_state->aml_offset; 766 acpi_ps_append_arg (op, arg); 767 } 768 INCREMENT_ARG_LIST (walk_state->arg_types); 769 } 770 771 /* Special processing for certain opcodes */ 772 773 switch (op->common.aml_opcode) { 774 case AML_METHOD_OP: 775 776 /* 777 * Skip parsing of control method 778 * because we don't have enough info in the first pass 779 * to parse it correctly. 780 * 781 * Save the length and address of the body 782 */ 783 op->named.data = parser_state->aml; 784 op->named.length = (u32) (parser_state->pkg_end - 785 parser_state->aml); 786 787 /* Skip body of method */ 788 789 parser_state->aml = parser_state->pkg_end; 790 walk_state->arg_count = 0; 791 break; 792 793 case AML_BUFFER_OP: 794 case AML_PACKAGE_OP: 795 case AML_VAR_PACKAGE_OP: 796 797 if ((op->common.parent) && 798 (op->common.parent->common.aml_opcode == AML_NAME_OP) && 799 (walk_state->descending_callback != acpi_ds_exec_begin_op)) { 800 /* 801 * Skip parsing of Buffers and Packages 802 * because we don't have enough info in the first pass 803 * to parse them correctly. 804 */ 805 op->named.data = aml_op_start; 806 op->named.length = (u32) (parser_state->pkg_end - 807 aml_op_start); 808 809 /* Skip body */ 810 811 parser_state->aml = parser_state->pkg_end; 812 walk_state->arg_count = 0; 813 } 814 break; 815 816 case AML_WHILE_OP: 817 818 if (walk_state->control_state) { 819 walk_state->control_state->control.package_end = 820 parser_state->pkg_end; 821 } 822 break; 823 824 default: 825 826 /* No action for all other opcodes */ 827 break; 828 } 829 break; 830 } 831 } 832 833 /* Check for arguments that need to be processed */ 834 835 if (walk_state->arg_count) { 836 /* 837 * There are arguments (complex ones), push Op and 838 * prepare for argument 839 */ 840 status = acpi_ps_push_scope (parser_state, op, 841 walk_state->arg_types, walk_state->arg_count); 842 if (ACPI_FAILURE (status)) { 843 goto close_this_op; 844 } 845 op = NULL; 846 continue; 847 } 848 849 /* 850 * All arguments have been processed -- Op is complete, 851 * prepare for next 852 */ 853 walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); 854 if (walk_state->op_info->flags & AML_NAMED) { 855 if (acpi_gbl_depth) { 856 acpi_gbl_depth--; 857 } 858 859 if (op->common.aml_opcode == AML_REGION_OP) { 860 /* 861 * Skip parsing of control method or opregion body, 862 * because we don't have enough info in the first pass 863 * to parse them correctly. 864 * 865 * Completed parsing an op_region declaration, we now 866 * know the length. 867 */ 868 op->named.length = (u32) (parser_state->aml - op->named.data); 869 } 870 } 871 872 if (walk_state->op_info->flags & AML_CREATE) { 873 /* 874 * Backup to beginning of create_xXXfield declaration (1 for 875 * Opcode) 876 * 877 * body_length is unknown until we parse the body 878 */ 879 op->named.length = (u32) (parser_state->aml - op->named.data); 880 } 881 882 /* This op complete, notify the dispatcher */ 883 884 if (walk_state->ascending_callback != NULL) { 885 walk_state->op = op; 886 walk_state->opcode = op->common.aml_opcode; 887 888 status = walk_state->ascending_callback (walk_state); 889 status = acpi_ps_next_parse_state (walk_state, op, status); 890 if (status == AE_CTRL_PENDING) { 891 status = AE_OK; 892 goto close_this_op; 893 } 894 } 895 896 897close_this_op: 898 /* 899 * Finished one argument of the containing scope 900 */ 901 parser_state->scope->parse_scope.arg_count--; 902 903 /* Close this Op (will result in parse subtree deletion) */ 904 905 acpi_ps_complete_this_op (walk_state, op); 906 op = NULL; 907 if (pre_op) { 908 acpi_ps_free_op (pre_op); 909 pre_op = NULL; 910 } 911 912 switch (status) { 913 case AE_OK: 914 break; 915 916 917 case AE_CTRL_TRANSFER: 918 919 /* We are about to transfer to a called method. */ 920 921 walk_state->prev_op = op; 922 walk_state->prev_arg_types = walk_state->arg_types; 923 return_ACPI_STATUS (status); 924 925 926 case AE_CTRL_END: 927 928 acpi_ps_pop_scope (parser_state, &op, 929 &walk_state->arg_types, &walk_state->arg_count); 930 931 if (op) { 932 walk_state->op = op; 933 walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); 934 walk_state->opcode = op->common.aml_opcode; 935 936 status = walk_state->ascending_callback (walk_state); 937 status = acpi_ps_next_parse_state (walk_state, op, status); 938 939 acpi_ps_complete_this_op (walk_state, op); 940 op = NULL; 941 } 942 status = AE_OK; 943 break; 944 945 946 case AE_CTRL_BREAK: 947 case AE_CTRL_CONTINUE: 948 949 /* Pop off scopes until we find the While */ 950 951 while (!op || (op->common.aml_opcode != AML_WHILE_OP)) { 952 acpi_ps_pop_scope (parser_state, &op, 953 &walk_state->arg_types, &walk_state->arg_count); 954 } 955 956 /* Close this iteration of the While loop */ 957 958 walk_state->op = op; 959 walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); 960 walk_state->opcode = op->common.aml_opcode; 961 962 status = walk_state->ascending_callback (walk_state); 963 status = acpi_ps_next_parse_state (walk_state, op, status); 964 965 acpi_ps_complete_this_op (walk_state, op); 966 op = NULL; 967 968 status = AE_OK; 969 break; 970 971 972 case AE_CTRL_TERMINATE: 973 974 status = AE_OK; 975 976 /* Clean up */ 977 do { 978 if (op) { 979 acpi_ps_complete_this_op (walk_state, op); 980 } 981 acpi_ps_pop_scope (parser_state, &op, 982 &walk_state->arg_types, &walk_state->arg_count); 983 984 } while (op); 985 986 return_ACPI_STATUS (status); 987 988 989 default: /* All other non-AE_OK status */ 990 991 do { 992 if (op) { 993 acpi_ps_complete_this_op (walk_state, op); 994 } 995 acpi_ps_pop_scope (parser_state, &op, 996 &walk_state->arg_types, &walk_state->arg_count); 997 998 } while (op); 999 1000 1001 /* 1002 * TBD: Cleanup parse ops on error 1003 */ 1004#if 0 1005 if (op == NULL) { 1006 acpi_ps_pop_scope (parser_state, &op, 1007 &walk_state->arg_types, &walk_state->arg_count); 1008 } 1009#endif 1010 walk_state->prev_op = op; 1011 walk_state->prev_arg_types = walk_state->arg_types; 1012 return_ACPI_STATUS (status); 1013 } 1014 1015 /* This scope complete? */ 1016 1017 if (acpi_ps_has_completed_scope (parser_state)) { 1018 acpi_ps_pop_scope (parser_state, &op, 1019 &walk_state->arg_types, &walk_state->arg_count); 1020 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", op)); 1021 } 1022 else { 1023 op = NULL; 1024 } 1025 1026 } /* while parser_state->Aml */ 1027 1028 1029 /* 1030 * Complete the last Op (if not completed), and clear the scope stack. 1031 * It is easily possible to end an AML "package" with an unbounded number 1032 * of open scopes (such as when several ASL blocks are closed with 1033 * sequential closing braces). We want to terminate each one cleanly. 1034 */ 1035 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", op)); 1036 do { 1037 if (op) { 1038 if (walk_state->ascending_callback != NULL) { 1039 walk_state->op = op; 1040 walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); 1041 walk_state->opcode = op->common.aml_opcode; 1042 1043 status = walk_state->ascending_callback (walk_state); 1044 status = acpi_ps_next_parse_state (walk_state, op, status); 1045 if (status == AE_CTRL_PENDING) { 1046 status = AE_OK; 1047 goto close_this_op; 1048 } 1049 1050 if (status == AE_CTRL_TERMINATE) { 1051 status = AE_OK; 1052 1053 /* Clean up */ 1054 do { 1055 if (op) { 1056 acpi_ps_complete_this_op (walk_state, op); 1057 } 1058 1059 acpi_ps_pop_scope (parser_state, &op, 1060 &walk_state->arg_types, &walk_state->arg_count); 1061 1062 } while (op); 1063 1064 return_ACPI_STATUS (status); 1065 } 1066 1067 else if (ACPI_FAILURE (status)) { 1068 acpi_ps_complete_this_op (walk_state, op); 1069 return_ACPI_STATUS (status); 1070 } 1071 } 1072 1073 acpi_ps_complete_this_op (walk_state, op); 1074 } 1075 1076 acpi_ps_pop_scope (parser_state, &op, &walk_state->arg_types, 1077 &walk_state->arg_count); 1078 1079 } while (op); 1080 1081 return_ACPI_STATUS (status); 1082} 1083 1084 1085/******************************************************************************* 1086 * 1087 * FUNCTION: acpi_ps_parse_aml 1088 * 1089 * PARAMETERS: walk_state - Current state 1090 * 1091 * 1092 * RETURN: Status 1093 * 1094 * DESCRIPTION: Parse raw AML and return a tree of ops 1095 * 1096 ******************************************************************************/ 1097 1098acpi_status 1099acpi_ps_parse_aml ( 1100 struct acpi_walk_state *walk_state) 1101{ 1102 acpi_status status; 1103 acpi_status terminate_status; 1104 struct acpi_thread_state *thread; 1105 struct acpi_thread_state *prev_walk_list = acpi_gbl_current_walk_list; 1106 struct acpi_walk_state *previous_walk_state; 1107 1108 1109 ACPI_FUNCTION_TRACE ("ps_parse_aml"); 1110 1111 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, 1112 "Entered with walk_state=%p Aml=%p size=%X\n", 1113 walk_state, walk_state->parser_state.aml, 1114 walk_state->parser_state.aml_size)); 1115 1116 1117 /* Create and initialize a new thread state */ 1118 1119 thread = acpi_ut_create_thread_state (); 1120 if (!thread) { 1121 return_ACPI_STATUS (AE_NO_MEMORY); 1122 } 1123 1124 walk_state->thread = thread; 1125 acpi_ds_push_walk_state (walk_state, thread); 1126 1127 /* 1128 * This global allows the AML debugger to get a handle to the currently 1129 * executing control method. 1130 */ 1131 acpi_gbl_current_walk_list = thread; 1132 1133 /* 1134 * Execute the walk loop as long as there is a valid Walk State. This 1135 * handles nested control method invocations without recursion. 1136 */ 1137 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "State=%p\n", walk_state)); 1138 1139 status = AE_OK; 1140 while (walk_state) { 1141 if (ACPI_SUCCESS (status)) { 1142 /* 1143 * The parse_loop executes AML until the method terminates 1144 * or calls another method. 1145 */ 1146 status = acpi_ps_parse_loop (walk_state); 1147 } 1148 1149 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, 1150 "Completed one call to walk loop, %s State=%p\n", 1151 acpi_format_exception (status), walk_state)); 1152 1153 if (status == AE_CTRL_TRANSFER) { 1154 /* 1155 * A method call was detected. 1156 * Transfer control to the called control method 1157 */ 1158 status = acpi_ds_call_control_method (thread, walk_state, NULL); 1159 1160 /* 1161 * If the transfer to the new method method call worked, a new walk 1162 * state was created -- get it 1163 */ 1164 walk_state = acpi_ds_get_current_walk_state (thread); 1165 continue; 1166 } 1167 else if (status == AE_CTRL_TERMINATE) { 1168 status = AE_OK; 1169 } 1170 else if ((status != AE_OK) && (walk_state->method_desc)) { 1171 ACPI_REPORT_METHOD_ERROR ("Method execution failed", 1172 walk_state->method_node, NULL, status); 1173 1174 /* Check for possible multi-thread reentrancy problem */ 1175 1176 if ((status == AE_ALREADY_EXISTS) && 1177 (!walk_state->method_desc->method.semaphore)) { 1178 /* 1179 * This method is marked not_serialized, but it tried to create 1180 * a named object, causing the second thread entrance to fail. 1181 * We will workaround this by marking the method permanently 1182 * as Serialized. 1183 */ 1184 walk_state->method_desc->method.method_flags |= AML_METHOD_SERIALIZED; 1185 walk_state->method_desc->method.concurrency = 1; 1186 } 1187 } 1188 1189 if (walk_state->method_desc) { 1190 /* Decrement the thread count on the method parse tree */ 1191 1192 if (walk_state->method_desc->method.thread_count) { 1193 walk_state->method_desc->method.thread_count--; 1194 } 1195 } 1196 1197 /* We are done with this walk, move on to the parent if any */ 1198 1199 walk_state = acpi_ds_pop_walk_state (thread); 1200 1201 /* Reset the current scope to the beginning of scope stack */ 1202 1203 acpi_ds_scope_stack_clear (walk_state); 1204 1205 /* 1206 * If we just returned from the execution of a control method, 1207 * there's lots of cleanup to do 1208 */ 1209 if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) { 1210 terminate_status = acpi_ds_terminate_control_method (walk_state); 1211 if (ACPI_FAILURE (terminate_status)) { 1212 ACPI_REPORT_ERROR (( 1213 "Could not terminate control method properly\n")); 1214 1215 /* Ignore error and continue */ 1216 } 1217 } 1218 1219 /* Delete this walk state and all linked control states */ 1220 1221 acpi_ps_cleanup_scope (&walk_state->parser_state); 1222 1223 previous_walk_state = walk_state; 1224 1225 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, 1226 "return_value=%p, implicit_value=%p State=%p\n", 1227 walk_state->return_desc, walk_state->implicit_return_obj, walk_state)); 1228 1229 /* Check if we have restarted a preempted walk */ 1230 1231 walk_state = acpi_ds_get_current_walk_state (thread); 1232 if (walk_state) { 1233 if (ACPI_SUCCESS (status)) { 1234 /* 1235 * There is another walk state, restart it. 1236 * If the method return value is not used by the parent, 1237 * The object is deleted 1238 */ 1239 if (!previous_walk_state->return_desc) { 1240 status = acpi_ds_restart_control_method (walk_state, 1241 previous_walk_state->implicit_return_obj); 1242 } 1243 else { 1244 /* 1245 * We have a valid return value, delete any implicit 1246 * return value. 1247 */ 1248 acpi_ds_clear_implicit_return (previous_walk_state); 1249 1250 status = acpi_ds_restart_control_method (walk_state, 1251 previous_walk_state->return_desc); 1252 } 1253 if (ACPI_SUCCESS (status)) { 1254 walk_state->walk_type |= ACPI_WALK_METHOD_RESTART; 1255 } 1256 } 1257 else { 1258 /* On error, delete any return object */ 1259 1260 acpi_ut_remove_reference (previous_walk_state->return_desc); 1261 } 1262 } 1263 1264 /* 1265 * Just completed a 1st-level method, save the final internal return 1266 * value (if any) 1267 */ 1268 else if (previous_walk_state->caller_return_desc) { 1269 if (previous_walk_state->implicit_return_obj) { 1270 *(previous_walk_state->caller_return_desc) = 1271 previous_walk_state->implicit_return_obj; 1272 } 1273 else { 1274 /* NULL if no return value */ 1275 1276 *(previous_walk_state->caller_return_desc) = 1277 previous_walk_state->return_desc; 1278 } 1279 } 1280 else { 1281 if (previous_walk_state->return_desc) { 1282 /* Caller doesn't want it, must delete it */ 1283 1284 acpi_ut_remove_reference (previous_walk_state->return_desc); 1285 } 1286 if (previous_walk_state->implicit_return_obj) { 1287 /* Caller doesn't want it, must delete it */ 1288 1289 acpi_ut_remove_reference (previous_walk_state->implicit_return_obj); 1290 } 1291 } 1292 1293 acpi_ds_delete_walk_state (previous_walk_state); 1294 } 1295 1296 /* Normal exit */ 1297 1298 acpi_ex_release_all_mutexes (thread); 1299 acpi_ut_delete_generic_state (ACPI_CAST_PTR (union acpi_generic_state, thread)); 1300 acpi_gbl_current_walk_list = prev_walk_list; 1301 return_ACPI_STATUS (status); 1302} 1303 1304