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