diff options
author | Robert Moore <robert.moore@intel.com> | 2005-06-24 00:00:00 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2005-07-13 23:45:36 -0400 |
commit | 73459f73e5d1602c59ebec114fc45185521353c1 (patch) | |
tree | 56c2183e345784d2be09c2f5d2530cf36221c55e /drivers/acpi/parser/psparse.c | |
parent | 88ac00f5a841dcfc5c682000f4a6add0add8caac (diff) |
ACPICA 20050617-0624 from Bob Moore <robert.moore@intel.com>
ACPICA 20050617:
Moved the object cache operations into the OS interface
layer (OSL) to allow the host OS to handle these operations
if desired (for example, the Linux OSL will invoke the
slab allocator). This support is optional; the compile
time define ACPI_USE_LOCAL_CACHE may be used to utilize
the original cache code in the ACPI CA core. The new OSL
interfaces are shown below. See utalloc.c for an example
implementation, and acpiosxf.h for the exact interface
definitions. Thanks to Alexey Starikovskiy.
acpi_os_create_cache
acpi_os_delete_cache
acpi_os_purge_cache
acpi_os_acquire_object
acpi_os_release_object
Modified the interfaces to acpi_os_acquire_lock and
acpi_os_release_lock to return and restore a flags
parameter. This fits better with many OS lock models.
Note: the current execution state (interrupt handler
or not) is no longer passed to these interfaces. If
necessary, the OSL must determine this state by itself, a
simple and fast operation. Thanks to Alexey Starikovskiy.
Fixed a problem in the ACPI table handling where a valid
XSDT was assumed present if the revision of the RSDP
was 2 or greater. According to the ACPI specification,
the XSDT is optional in all cases, and the table manager
therefore now checks for both an RSDP >=2 and a valid
XSDT pointer. Otherwise, the RSDT pointer is used.
Some ACPI 2.0 compliant BIOSs contain only the RSDT.
Fixed an interpreter problem with the Mid() operator in the
case of an input string where the resulting output string
is of zero length. It now correctly returns a valid,
null terminated string object instead of a string object
with a null pointer.
Fixed a problem with the control method argument handling
to allow a store to an Arg object that already contains an
object of type Device. The Device object is now correctly
overwritten. Previously, an error was returned.
ACPICA 20050624:
Modified the new OSL cache interfaces to use ACPI_CACHE_T
as the type for the host-defined cache object. This allows
the OSL implementation to define and type this object in
any manner desired, simplifying the OSL implementation.
For example, ACPI_CACHE_T is defined as kmem_cache_t for
Linux, and should be defined in the OS-specific header
file for other operating systems as required.
Changed the interface to AcpiOsAcquireObject to directly
return the requested object as the function return (instead
of ACPI_STATUS.) This change was made for performance
reasons, since this is the purpose of the interface in the
first place. acpi_os_acquire_object is now similar to the
acpi_os_allocate interface. Thanks to Alexey Starikovskiy.
Modified the initialization sequence in
acpi_initialize_subsystem to call the OSL interface
acpi_osl_initialize first, before any local initialization.
This change was required because the global initialization
now calls OSL interfaces.
Restructured the code base to split some files because
of size and/or because the code logically belonged in a
separate file. New files are listed below.
utilities/utcache.c /* Local cache interfaces */
utilities/utmutex.c /* Local mutex support */
utilities/utstate.c /* State object support */
parser/psloop.c /* Main AML parse loop */
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/parser/psparse.c')
-rw-r--r-- | drivers/acpi/parser/psparse.c | 728 |
1 files changed, 4 insertions, 724 deletions
diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c index bdbe0d99486f..16b84a3d0436 100644 --- a/drivers/acpi/parser/psparse.c +++ b/drivers/acpi/parser/psparse.c | |||
@@ -62,26 +62,6 @@ | |||
62 | ACPI_MODULE_NAME ("psparse") | 62 | ACPI_MODULE_NAME ("psparse") |
63 | 63 | ||
64 | 64 | ||
65 | static u32 acpi_gbl_depth = 0; | ||
66 | |||
67 | /* Local prototypes */ | ||
68 | |||
69 | static acpi_status | ||
70 | acpi_ps_complete_this_op ( | ||
71 | struct acpi_walk_state *walk_state, | ||
72 | union acpi_parse_object *op); | ||
73 | |||
74 | static acpi_status | ||
75 | acpi_ps_next_parse_state ( | ||
76 | struct acpi_walk_state *walk_state, | ||
77 | union acpi_parse_object *op, | ||
78 | acpi_status callback_status); | ||
79 | |||
80 | static acpi_status | ||
81 | acpi_ps_parse_loop ( | ||
82 | struct acpi_walk_state *walk_state); | ||
83 | |||
84 | |||
85 | /******************************************************************************* | 65 | /******************************************************************************* |
86 | * | 66 | * |
87 | * FUNCTION: acpi_ps_get_opcode_size | 67 | * FUNCTION: acpi_ps_get_opcode_size |
@@ -134,8 +114,8 @@ acpi_ps_peek_opcode ( | |||
134 | aml = parser_state->aml; | 114 | aml = parser_state->aml; |
135 | opcode = (u16) ACPI_GET8 (aml); | 115 | opcode = (u16) ACPI_GET8 (aml); |
136 | 116 | ||
137 | if (opcode == AML_EXTOP) { | 117 | if (opcode == AML_EXTENDED_OP_PREFIX) { |
138 | /* Extended opcode */ | 118 | /* Extended opcode, get the second opcode byte */ |
139 | 119 | ||
140 | aml++; | 120 | aml++; |
141 | opcode = (u16) ((opcode << 8) | ACPI_GET8 (aml)); | 121 | opcode = (u16) ((opcode << 8) | ACPI_GET8 (aml)); |
@@ -158,7 +138,7 @@ acpi_ps_peek_opcode ( | |||
158 | * | 138 | * |
159 | ******************************************************************************/ | 139 | ******************************************************************************/ |
160 | 140 | ||
161 | static acpi_status | 141 | acpi_status |
162 | acpi_ps_complete_this_op ( | 142 | acpi_ps_complete_this_op ( |
163 | struct acpi_walk_state *walk_state, | 143 | struct acpi_walk_state *walk_state, |
164 | union acpi_parse_object *op) | 144 | union acpi_parse_object *op) |
@@ -331,7 +311,7 @@ allocate_error: | |||
331 | * | 311 | * |
332 | ******************************************************************************/ | 312 | ******************************************************************************/ |
333 | 313 | ||
334 | static acpi_status | 314 | acpi_status |
335 | acpi_ps_next_parse_state ( | 315 | acpi_ps_next_parse_state ( |
336 | struct acpi_walk_state *walk_state, | 316 | struct acpi_walk_state *walk_state, |
337 | union acpi_parse_object *op, | 317 | union acpi_parse_object *op, |
@@ -441,706 +421,6 @@ acpi_ps_next_parse_state ( | |||
441 | 421 | ||
442 | /******************************************************************************* | 422 | /******************************************************************************* |
443 | * | 423 | * |
444 | * FUNCTION: acpi_ps_parse_loop | ||
445 | * | ||
446 | * PARAMETERS: walk_state - Current state | ||
447 | * | ||
448 | * RETURN: Status | ||
449 | * | ||
450 | * DESCRIPTION: Parse AML (pointed to by the current parser state) and return | ||
451 | * a tree of ops. | ||
452 | * | ||
453 | ******************************************************************************/ | ||
454 | |||
455 | static acpi_status | ||
456 | acpi_ps_parse_loop ( | ||
457 | struct acpi_walk_state *walk_state) | ||
458 | { | ||
459 | acpi_status status = AE_OK; | ||
460 | acpi_status status2; | ||
461 | union acpi_parse_object *op = NULL; /* current op */ | ||
462 | union acpi_parse_object *arg = NULL; | ||
463 | union acpi_parse_object *pre_op = NULL; | ||
464 | struct acpi_parse_state *parser_state; | ||
465 | u8 *aml_op_start = NULL; | ||
466 | |||
467 | |||
468 | ACPI_FUNCTION_TRACE_PTR ("ps_parse_loop", walk_state); | ||
469 | |||
470 | if (walk_state->descending_callback == NULL) { | ||
471 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
472 | } | ||
473 | |||
474 | parser_state = &walk_state->parser_state; | ||
475 | walk_state->arg_types = 0; | ||
476 | |||
477 | #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) | ||
478 | |||
479 | if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) { | ||
480 | /* We are restarting a preempted control method */ | ||
481 | |||
482 | if (acpi_ps_has_completed_scope (parser_state)) { | ||
483 | /* | ||
484 | * We must check if a predicate to an IF or WHILE statement | ||
485 | * was just completed | ||
486 | */ | ||
487 | if ((parser_state->scope->parse_scope.op) && | ||
488 | ((parser_state->scope->parse_scope.op->common.aml_opcode == AML_IF_OP) || | ||
489 | (parser_state->scope->parse_scope.op->common.aml_opcode == AML_WHILE_OP)) && | ||
490 | (walk_state->control_state) && | ||
491 | (walk_state->control_state->common.state == | ||
492 | ACPI_CONTROL_PREDICATE_EXECUTING)) { | ||
493 | /* | ||
494 | * A predicate was just completed, get the value of the | ||
495 | * predicate and branch based on that value | ||
496 | */ | ||
497 | walk_state->op = NULL; | ||
498 | status = acpi_ds_get_predicate_value (walk_state, ACPI_TO_POINTER (TRUE)); | ||
499 | if (ACPI_FAILURE (status) && | ||
500 | ((status & AE_CODE_MASK) != AE_CODE_CONTROL)) { | ||
501 | if (status == AE_AML_NO_RETURN_VALUE) { | ||
502 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
503 | "Invoked method did not return a value, %s\n", | ||
504 | acpi_format_exception (status))); | ||
505 | |||
506 | } | ||
507 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
508 | "get_predicate Failed, %s\n", | ||
509 | acpi_format_exception (status))); | ||
510 | return_ACPI_STATUS (status); | ||
511 | } | ||
512 | |||
513 | status = acpi_ps_next_parse_state (walk_state, op, status); | ||
514 | } | ||
515 | |||
516 | acpi_ps_pop_scope (parser_state, &op, | ||
517 | &walk_state->arg_types, &walk_state->arg_count); | ||
518 | ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", op)); | ||
519 | } | ||
520 | else if (walk_state->prev_op) { | ||
521 | /* We were in the middle of an op */ | ||
522 | |||
523 | op = walk_state->prev_op; | ||
524 | walk_state->arg_types = walk_state->prev_arg_types; | ||
525 | } | ||
526 | } | ||
527 | #endif | ||
528 | |||
529 | /* Iterative parsing loop, while there is more AML to process: */ | ||
530 | |||
531 | while ((parser_state->aml < parser_state->aml_end) || (op)) { | ||
532 | aml_op_start = parser_state->aml; | ||
533 | if (!op) { | ||
534 | /* Get the next opcode from the AML stream */ | ||
535 | |||
536 | walk_state->aml_offset = (u32) ACPI_PTR_DIFF (parser_state->aml, | ||
537 | parser_state->aml_start); | ||
538 | walk_state->opcode = acpi_ps_peek_opcode (parser_state); | ||
539 | |||
540 | /* | ||
541 | * First cut to determine what we have found: | ||
542 | * 1) A valid AML opcode | ||
543 | * 2) A name string | ||
544 | * 3) An unknown/invalid opcode | ||
545 | */ | ||
546 | walk_state->op_info = acpi_ps_get_opcode_info (walk_state->opcode); | ||
547 | switch (walk_state->op_info->class) { | ||
548 | case AML_CLASS_ASCII: | ||
549 | case AML_CLASS_PREFIX: | ||
550 | /* | ||
551 | * Starts with a valid prefix or ASCII char, this is a name | ||
552 | * string. Convert the bare name string to a namepath. | ||
553 | */ | ||
554 | walk_state->opcode = AML_INT_NAMEPATH_OP; | ||
555 | walk_state->arg_types = ARGP_NAMESTRING; | ||
556 | break; | ||
557 | |||
558 | case AML_CLASS_UNKNOWN: | ||
559 | |||
560 | /* The opcode is unrecognized. Just skip unknown opcodes */ | ||
561 | |||
562 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
563 | "Found unknown opcode %X at AML address %p offset %X, ignoring\n", | ||
564 | walk_state->opcode, parser_state->aml, walk_state->aml_offset)); | ||
565 | |||
566 | ACPI_DUMP_BUFFER (parser_state->aml, 128); | ||
567 | |||
568 | /* Assume one-byte bad opcode */ | ||
569 | |||
570 | parser_state->aml++; | ||
571 | continue; | ||
572 | |||
573 | default: | ||
574 | |||
575 | /* Found opcode info, this is a normal opcode */ | ||
576 | |||
577 | parser_state->aml += acpi_ps_get_opcode_size (walk_state->opcode); | ||
578 | walk_state->arg_types = walk_state->op_info->parse_args; | ||
579 | break; | ||
580 | } | ||
581 | |||
582 | /* Create Op structure and append to parent's argument list */ | ||
583 | |||
584 | if (walk_state->op_info->flags & AML_NAMED) { | ||
585 | /* Allocate a new pre_op if necessary */ | ||
586 | |||
587 | if (!pre_op) { | ||
588 | pre_op = acpi_ps_alloc_op (walk_state->opcode); | ||
589 | if (!pre_op) { | ||
590 | status = AE_NO_MEMORY; | ||
591 | goto close_this_op; | ||
592 | } | ||
593 | } | ||
594 | |||
595 | pre_op->common.value.arg = NULL; | ||
596 | pre_op->common.aml_opcode = walk_state->opcode; | ||
597 | |||
598 | /* | ||
599 | * Get and append arguments until we find the node that contains | ||
600 | * the name (the type ARGP_NAME). | ||
601 | */ | ||
602 | while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) && | ||
603 | (GET_CURRENT_ARG_TYPE (walk_state->arg_types) != ARGP_NAME)) { | ||
604 | status = acpi_ps_get_next_arg (walk_state, parser_state, | ||
605 | GET_CURRENT_ARG_TYPE (walk_state->arg_types), &arg); | ||
606 | if (ACPI_FAILURE (status)) { | ||
607 | goto close_this_op; | ||
608 | } | ||
609 | |||
610 | acpi_ps_append_arg (pre_op, arg); | ||
611 | INCREMENT_ARG_LIST (walk_state->arg_types); | ||
612 | } | ||
613 | |||
614 | /* | ||
615 | * Make sure that we found a NAME and didn't run out of | ||
616 | * arguments | ||
617 | */ | ||
618 | if (!GET_CURRENT_ARG_TYPE (walk_state->arg_types)) { | ||
619 | status = AE_AML_NO_OPERAND; | ||
620 | goto close_this_op; | ||
621 | } | ||
622 | |||
623 | /* We know that this arg is a name, move to next arg */ | ||
624 | |||
625 | INCREMENT_ARG_LIST (walk_state->arg_types); | ||
626 | |||
627 | /* | ||
628 | * Find the object. This will either insert the object into | ||
629 | * the namespace or simply look it up | ||
630 | */ | ||
631 | walk_state->op = NULL; | ||
632 | |||
633 | status = walk_state->descending_callback (walk_state, &op); | ||
634 | if (ACPI_FAILURE (status)) { | ||
635 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
636 | "During name lookup/catalog, %s\n", | ||
637 | acpi_format_exception (status))); | ||
638 | goto close_this_op; | ||
639 | } | ||
640 | |||
641 | if (!op) { | ||
642 | continue; | ||
643 | } | ||
644 | |||
645 | status = acpi_ps_next_parse_state (walk_state, op, status); | ||
646 | if (status == AE_CTRL_PENDING) { | ||
647 | status = AE_OK; | ||
648 | goto close_this_op; | ||
649 | } | ||
650 | |||
651 | if (ACPI_FAILURE (status)) { | ||
652 | goto close_this_op; | ||
653 | } | ||
654 | |||
655 | acpi_ps_append_arg (op, pre_op->common.value.arg); | ||
656 | acpi_gbl_depth++; | ||
657 | |||
658 | if (op->common.aml_opcode == AML_REGION_OP) { | ||
659 | /* | ||
660 | * Defer final parsing of an operation_region body, | ||
661 | * because we don't have enough info in the first pass | ||
662 | * to parse it correctly (i.e., there may be method | ||
663 | * calls within the term_arg elements of the body.) | ||
664 | * | ||
665 | * However, we must continue parsing because | ||
666 | * the opregion is not a standalone package -- | ||
667 | * we don't know where the end is at this point. | ||
668 | * | ||
669 | * (Length is unknown until parse of the body complete) | ||
670 | */ | ||
671 | op->named.data = aml_op_start; | ||
672 | op->named.length = 0; | ||
673 | } | ||
674 | } | ||
675 | else { | ||
676 | /* Not a named opcode, just allocate Op and append to parent */ | ||
677 | |||
678 | walk_state->op_info = acpi_ps_get_opcode_info (walk_state->opcode); | ||
679 | op = acpi_ps_alloc_op (walk_state->opcode); | ||
680 | if (!op) { | ||
681 | status = AE_NO_MEMORY; | ||
682 | goto close_this_op; | ||
683 | } | ||
684 | |||
685 | if (walk_state->op_info->flags & AML_CREATE) { | ||
686 | /* | ||
687 | * Backup to beginning of create_xXXfield declaration | ||
688 | * body_length is unknown until we parse the body | ||
689 | */ | ||
690 | op->named.data = aml_op_start; | ||
691 | op->named.length = 0; | ||
692 | } | ||
693 | |||
694 | acpi_ps_append_arg (acpi_ps_get_parent_scope (parser_state), op); | ||
695 | |||
696 | if ((walk_state->descending_callback != NULL)) { | ||
697 | /* | ||
698 | * Find the object. This will either insert the object into | ||
699 | * the namespace or simply look it up | ||
700 | */ | ||
701 | walk_state->op = op; | ||
702 | |||
703 | status = walk_state->descending_callback (walk_state, &op); | ||
704 | status = acpi_ps_next_parse_state (walk_state, op, status); | ||
705 | if (status == AE_CTRL_PENDING) { | ||
706 | status = AE_OK; | ||
707 | goto close_this_op; | ||
708 | } | ||
709 | |||
710 | if (ACPI_FAILURE (status)) { | ||
711 | goto close_this_op; | ||
712 | } | ||
713 | } | ||
714 | } | ||
715 | |||
716 | op->common.aml_offset = walk_state->aml_offset; | ||
717 | |||
718 | if (walk_state->op_info) { | ||
719 | ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, | ||
720 | "Opcode %4.4X [%s] Op %p Aml %p aml_offset %5.5X\n", | ||
721 | (u32) op->common.aml_opcode, walk_state->op_info->name, | ||
722 | op, parser_state->aml, op->common.aml_offset)); | ||
723 | } | ||
724 | } | ||
725 | |||
726 | |||
727 | /* | ||
728 | * Start arg_count at zero because we don't know if there are | ||
729 | * any args yet | ||
730 | */ | ||
731 | walk_state->arg_count = 0; | ||
732 | |||
733 | /* Are there any arguments that must be processed? */ | ||
734 | |||
735 | if (walk_state->arg_types) { | ||
736 | /* Get arguments */ | ||
737 | |||
738 | switch (op->common.aml_opcode) { | ||
739 | case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ | ||
740 | case AML_WORD_OP: /* AML_WORDDATA_ARG */ | ||
741 | case AML_DWORD_OP: /* AML_DWORDATA_ARG */ | ||
742 | case AML_QWORD_OP: /* AML_QWORDATA_ARG */ | ||
743 | case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */ | ||
744 | |||
745 | /* Fill in constant or string argument directly */ | ||
746 | |||
747 | acpi_ps_get_next_simple_arg (parser_state, | ||
748 | GET_CURRENT_ARG_TYPE (walk_state->arg_types), op); | ||
749 | break; | ||
750 | |||
751 | case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */ | ||
752 | |||
753 | status = acpi_ps_get_next_namepath (walk_state, parser_state, op, 1); | ||
754 | if (ACPI_FAILURE (status)) { | ||
755 | goto close_this_op; | ||
756 | } | ||
757 | |||
758 | walk_state->arg_types = 0; | ||
759 | break; | ||
760 | |||
761 | default: | ||
762 | /* | ||
763 | * Op is not a constant or string, append each argument | ||
764 | * to the Op | ||
765 | */ | ||
766 | while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) && | ||
767 | !walk_state->arg_count) { | ||
768 | walk_state->aml_offset = (u32) | ||
769 | ACPI_PTR_DIFF (parser_state->aml, parser_state->aml_start); | ||
770 | |||
771 | status = acpi_ps_get_next_arg (walk_state, parser_state, | ||
772 | GET_CURRENT_ARG_TYPE (walk_state->arg_types), | ||
773 | &arg); | ||
774 | if (ACPI_FAILURE (status)) { | ||
775 | goto close_this_op; | ||
776 | } | ||
777 | |||
778 | if (arg) { | ||
779 | arg->common.aml_offset = walk_state->aml_offset; | ||
780 | acpi_ps_append_arg (op, arg); | ||
781 | } | ||
782 | INCREMENT_ARG_LIST (walk_state->arg_types); | ||
783 | } | ||
784 | |||
785 | /* Special processing for certain opcodes */ | ||
786 | |||
787 | if (walk_state->pass_number <= ACPI_IMODE_LOAD_PASS1) { | ||
788 | switch (op->common.aml_opcode) { | ||
789 | case AML_IF_OP: | ||
790 | case AML_ELSE_OP: | ||
791 | case AML_WHILE_OP: | ||
792 | |||
793 | /* Skip body of if/else/while in pass 1 */ | ||
794 | |||
795 | parser_state->aml = parser_state->pkg_end; | ||
796 | walk_state->arg_count = 0; | ||
797 | break; | ||
798 | |||
799 | default: | ||
800 | break; | ||
801 | } | ||
802 | } | ||
803 | |||
804 | switch (op->common.aml_opcode) { | ||
805 | case AML_METHOD_OP: | ||
806 | |||
807 | /* | ||
808 | * Skip parsing of control method | ||
809 | * because we don't have enough info in the first pass | ||
810 | * to parse it correctly. | ||
811 | * | ||
812 | * Save the length and address of the body | ||
813 | */ | ||
814 | op->named.data = parser_state->aml; | ||
815 | op->named.length = (u32) (parser_state->pkg_end - | ||
816 | parser_state->aml); | ||
817 | |||
818 | /* Skip body of method */ | ||
819 | |||
820 | parser_state->aml = parser_state->pkg_end; | ||
821 | walk_state->arg_count = 0; | ||
822 | break; | ||
823 | |||
824 | case AML_BUFFER_OP: | ||
825 | case AML_PACKAGE_OP: | ||
826 | case AML_VAR_PACKAGE_OP: | ||
827 | |||
828 | if ((op->common.parent) && | ||
829 | (op->common.parent->common.aml_opcode == AML_NAME_OP) && | ||
830 | (walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2)) { | ||
831 | /* | ||
832 | * Skip parsing of Buffers and Packages | ||
833 | * because we don't have enough info in the first pass | ||
834 | * to parse them correctly. | ||
835 | */ | ||
836 | op->named.data = aml_op_start; | ||
837 | op->named.length = (u32) (parser_state->pkg_end - | ||
838 | aml_op_start); | ||
839 | |||
840 | /* Skip body */ | ||
841 | |||
842 | parser_state->aml = parser_state->pkg_end; | ||
843 | walk_state->arg_count = 0; | ||
844 | } | ||
845 | break; | ||
846 | |||
847 | case AML_WHILE_OP: | ||
848 | |||
849 | if (walk_state->control_state) { | ||
850 | walk_state->control_state->control.package_end = | ||
851 | parser_state->pkg_end; | ||
852 | } | ||
853 | break; | ||
854 | |||
855 | default: | ||
856 | |||
857 | /* No action for all other opcodes */ | ||
858 | break; | ||
859 | } | ||
860 | break; | ||
861 | } | ||
862 | } | ||
863 | |||
864 | /* Check for arguments that need to be processed */ | ||
865 | |||
866 | if (walk_state->arg_count) { | ||
867 | /* | ||
868 | * There are arguments (complex ones), push Op and | ||
869 | * prepare for argument | ||
870 | */ | ||
871 | status = acpi_ps_push_scope (parser_state, op, | ||
872 | walk_state->arg_types, walk_state->arg_count); | ||
873 | if (ACPI_FAILURE (status)) { | ||
874 | goto close_this_op; | ||
875 | } | ||
876 | op = NULL; | ||
877 | continue; | ||
878 | } | ||
879 | |||
880 | /* | ||
881 | * All arguments have been processed -- Op is complete, | ||
882 | * prepare for next | ||
883 | */ | ||
884 | walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); | ||
885 | if (walk_state->op_info->flags & AML_NAMED) { | ||
886 | if (acpi_gbl_depth) { | ||
887 | acpi_gbl_depth--; | ||
888 | } | ||
889 | |||
890 | if (op->common.aml_opcode == AML_REGION_OP) { | ||
891 | /* | ||
892 | * Skip parsing of control method or opregion body, | ||
893 | * because we don't have enough info in the first pass | ||
894 | * to parse them correctly. | ||
895 | * | ||
896 | * Completed parsing an op_region declaration, we now | ||
897 | * know the length. | ||
898 | */ | ||
899 | op->named.length = (u32) (parser_state->aml - op->named.data); | ||
900 | } | ||
901 | } | ||
902 | |||
903 | if (walk_state->op_info->flags & AML_CREATE) { | ||
904 | /* | ||
905 | * Backup to beginning of create_xXXfield declaration (1 for | ||
906 | * Opcode) | ||
907 | * | ||
908 | * body_length is unknown until we parse the body | ||
909 | */ | ||
910 | op->named.length = (u32) (parser_state->aml - op->named.data); | ||
911 | } | ||
912 | |||
913 | /* This op complete, notify the dispatcher */ | ||
914 | |||
915 | if (walk_state->ascending_callback != NULL) { | ||
916 | walk_state->op = op; | ||
917 | walk_state->opcode = op->common.aml_opcode; | ||
918 | |||
919 | status = walk_state->ascending_callback (walk_state); | ||
920 | status = acpi_ps_next_parse_state (walk_state, op, status); | ||
921 | if (status == AE_CTRL_PENDING) { | ||
922 | status = AE_OK; | ||
923 | goto close_this_op; | ||
924 | } | ||
925 | } | ||
926 | |||
927 | |||
928 | close_this_op: | ||
929 | /* | ||
930 | * Finished one argument of the containing scope | ||
931 | */ | ||
932 | parser_state->scope->parse_scope.arg_count--; | ||
933 | |||
934 | /* Finished with pre_op */ | ||
935 | |||
936 | if (pre_op) { | ||
937 | acpi_ps_free_op (pre_op); | ||
938 | pre_op = NULL; | ||
939 | } | ||
940 | |||
941 | /* Close this Op (will result in parse subtree deletion) */ | ||
942 | |||
943 | status2 = acpi_ps_complete_this_op (walk_state, op); | ||
944 | if (ACPI_FAILURE (status2)) { | ||
945 | return_ACPI_STATUS (status2); | ||
946 | } | ||
947 | op = NULL; | ||
948 | |||
949 | switch (status) { | ||
950 | case AE_OK: | ||
951 | break; | ||
952 | |||
953 | |||
954 | case AE_CTRL_TRANSFER: | ||
955 | |||
956 | /* We are about to transfer to a called method. */ | ||
957 | |||
958 | walk_state->prev_op = op; | ||
959 | walk_state->prev_arg_types = walk_state->arg_types; | ||
960 | return_ACPI_STATUS (status); | ||
961 | |||
962 | |||
963 | case AE_CTRL_END: | ||
964 | |||
965 | acpi_ps_pop_scope (parser_state, &op, | ||
966 | &walk_state->arg_types, &walk_state->arg_count); | ||
967 | |||
968 | if (op) { | ||
969 | walk_state->op = op; | ||
970 | walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); | ||
971 | walk_state->opcode = op->common.aml_opcode; | ||
972 | |||
973 | status = walk_state->ascending_callback (walk_state); | ||
974 | status = acpi_ps_next_parse_state (walk_state, op, status); | ||
975 | |||
976 | status2 = acpi_ps_complete_this_op (walk_state, op); | ||
977 | if (ACPI_FAILURE (status2)) { | ||
978 | return_ACPI_STATUS (status2); | ||
979 | } | ||
980 | op = NULL; | ||
981 | } | ||
982 | status = AE_OK; | ||
983 | break; | ||
984 | |||
985 | |||
986 | case AE_CTRL_BREAK: | ||
987 | case AE_CTRL_CONTINUE: | ||
988 | |||
989 | /* Pop off scopes until we find the While */ | ||
990 | |||
991 | while (!op || (op->common.aml_opcode != AML_WHILE_OP)) { | ||
992 | acpi_ps_pop_scope (parser_state, &op, | ||
993 | &walk_state->arg_types, &walk_state->arg_count); | ||
994 | } | ||
995 | |||
996 | /* Close this iteration of the While loop */ | ||
997 | |||
998 | walk_state->op = op; | ||
999 | walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); | ||
1000 | walk_state->opcode = op->common.aml_opcode; | ||
1001 | |||
1002 | status = walk_state->ascending_callback (walk_state); | ||
1003 | status = acpi_ps_next_parse_state (walk_state, op, status); | ||
1004 | |||
1005 | status2 = acpi_ps_complete_this_op (walk_state, op); | ||
1006 | if (ACPI_FAILURE (status2)) { | ||
1007 | return_ACPI_STATUS (status2); | ||
1008 | } | ||
1009 | op = NULL; | ||
1010 | |||
1011 | status = AE_OK; | ||
1012 | break; | ||
1013 | |||
1014 | |||
1015 | case AE_CTRL_TERMINATE: | ||
1016 | |||
1017 | status = AE_OK; | ||
1018 | |||
1019 | /* Clean up */ | ||
1020 | do { | ||
1021 | if (op) { | ||
1022 | status2 = acpi_ps_complete_this_op (walk_state, op); | ||
1023 | if (ACPI_FAILURE (status2)) { | ||
1024 | return_ACPI_STATUS (status2); | ||
1025 | } | ||
1026 | } | ||
1027 | acpi_ps_pop_scope (parser_state, &op, | ||
1028 | &walk_state->arg_types, &walk_state->arg_count); | ||
1029 | |||
1030 | } while (op); | ||
1031 | |||
1032 | return_ACPI_STATUS (status); | ||
1033 | |||
1034 | |||
1035 | default: /* All other non-AE_OK status */ | ||
1036 | |||
1037 | do { | ||
1038 | if (op) { | ||
1039 | status2 = acpi_ps_complete_this_op (walk_state, op); | ||
1040 | if (ACPI_FAILURE (status2)) { | ||
1041 | return_ACPI_STATUS (status2); | ||
1042 | } | ||
1043 | } | ||
1044 | acpi_ps_pop_scope (parser_state, &op, | ||
1045 | &walk_state->arg_types, &walk_state->arg_count); | ||
1046 | |||
1047 | } while (op); | ||
1048 | |||
1049 | |||
1050 | /* | ||
1051 | * TBD: Cleanup parse ops on error | ||
1052 | */ | ||
1053 | #if 0 | ||
1054 | if (op == NULL) { | ||
1055 | acpi_ps_pop_scope (parser_state, &op, | ||
1056 | &walk_state->arg_types, &walk_state->arg_count); | ||
1057 | } | ||
1058 | #endif | ||
1059 | walk_state->prev_op = op; | ||
1060 | walk_state->prev_arg_types = walk_state->arg_types; | ||
1061 | return_ACPI_STATUS (status); | ||
1062 | } | ||
1063 | |||
1064 | /* This scope complete? */ | ||
1065 | |||
1066 | if (acpi_ps_has_completed_scope (parser_state)) { | ||
1067 | acpi_ps_pop_scope (parser_state, &op, | ||
1068 | &walk_state->arg_types, &walk_state->arg_count); | ||
1069 | ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", op)); | ||
1070 | } | ||
1071 | else { | ||
1072 | op = NULL; | ||
1073 | } | ||
1074 | |||
1075 | } /* while parser_state->Aml */ | ||
1076 | |||
1077 | |||
1078 | /* | ||
1079 | * Complete the last Op (if not completed), and clear the scope stack. | ||
1080 | * It is easily possible to end an AML "package" with an unbounded number | ||
1081 | * of open scopes (such as when several ASL blocks are closed with | ||
1082 | * sequential closing braces). We want to terminate each one cleanly. | ||
1083 | */ | ||
1084 | ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", op)); | ||
1085 | do { | ||
1086 | if (op) { | ||
1087 | if (walk_state->ascending_callback != NULL) { | ||
1088 | walk_state->op = op; | ||
1089 | walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); | ||
1090 | walk_state->opcode = op->common.aml_opcode; | ||
1091 | |||
1092 | status = walk_state->ascending_callback (walk_state); | ||
1093 | status = acpi_ps_next_parse_state (walk_state, op, status); | ||
1094 | if (status == AE_CTRL_PENDING) { | ||
1095 | status = AE_OK; | ||
1096 | goto close_this_op; | ||
1097 | } | ||
1098 | |||
1099 | if (status == AE_CTRL_TERMINATE) { | ||
1100 | status = AE_OK; | ||
1101 | |||
1102 | /* Clean up */ | ||
1103 | do { | ||
1104 | if (op) { | ||
1105 | status2 = acpi_ps_complete_this_op (walk_state, op); | ||
1106 | if (ACPI_FAILURE (status2)) { | ||
1107 | return_ACPI_STATUS (status2); | ||
1108 | } | ||
1109 | } | ||
1110 | |||
1111 | acpi_ps_pop_scope (parser_state, &op, | ||
1112 | &walk_state->arg_types, &walk_state->arg_count); | ||
1113 | |||
1114 | } while (op); | ||
1115 | |||
1116 | return_ACPI_STATUS (status); | ||
1117 | } | ||
1118 | |||
1119 | else if (ACPI_FAILURE (status)) { | ||
1120 | /* First error is most important */ | ||
1121 | |||
1122 | (void) acpi_ps_complete_this_op (walk_state, op); | ||
1123 | return_ACPI_STATUS (status); | ||
1124 | } | ||
1125 | } | ||
1126 | |||
1127 | status2 = acpi_ps_complete_this_op (walk_state, op); | ||
1128 | if (ACPI_FAILURE (status2)) { | ||
1129 | return_ACPI_STATUS (status2); | ||
1130 | } | ||
1131 | } | ||
1132 | |||
1133 | acpi_ps_pop_scope (parser_state, &op, &walk_state->arg_types, | ||
1134 | &walk_state->arg_count); | ||
1135 | |||
1136 | } while (op); | ||
1137 | |||
1138 | return_ACPI_STATUS (status); | ||
1139 | } | ||
1140 | |||
1141 | |||
1142 | /******************************************************************************* | ||
1143 | * | ||
1144 | * FUNCTION: acpi_ps_parse_aml | 424 | * FUNCTION: acpi_ps_parse_aml |
1145 | * | 425 | * |
1146 | * PARAMETERS: walk_state - Current state | 426 | * PARAMETERS: walk_state - Current state |