linux/drivers/acpi/acpica/psloop.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Module Name: psloop - Main AML parse loop
   4 *
   5 *****************************************************************************/
   6
   7/*
   8 * Copyright (C) 2000 - 2012, Intel Corp.
   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 * Parse the AML and build an operation tree as most interpreters, (such as
  46 * Perl) do. Parsing is done by hand rather than with a YACC generated parser
  47 * to tightly constrain stack and dynamic memory usage. Parsing is kept
  48 * flexible and the code fairly compact by parsing based on a list of AML
  49 * opcode templates in aml_op_info[].
  50 */
  51
  52#include <acpi/acpi.h>
  53#include "accommon.h"
  54#include "acparser.h"
  55#include "acdispat.h"
  56#include "amlcode.h"
  57
  58#define _COMPONENT          ACPI_PARSER
  59ACPI_MODULE_NAME("psloop")
  60
  61static u32 acpi_gbl_depth = 0;
  62
  63/* Local prototypes */
  64
  65static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state);
  66
  67static acpi_status
  68acpi_ps_build_named_op(struct acpi_walk_state *walk_state,
  69                       u8 * aml_op_start,
  70                       union acpi_parse_object *unnamed_op,
  71                       union acpi_parse_object **op);
  72
  73static acpi_status
  74acpi_ps_create_op(struct acpi_walk_state *walk_state,
  75                  u8 * aml_op_start, union acpi_parse_object **new_op);
  76
  77static acpi_status
  78acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
  79                      u8 * aml_op_start, union acpi_parse_object *op);
  80
  81static acpi_status
  82acpi_ps_complete_op(struct acpi_walk_state *walk_state,
  83                    union acpi_parse_object **op, acpi_status status);
  84
  85static acpi_status
  86acpi_ps_complete_final_op(struct acpi_walk_state *walk_state,
  87                          union acpi_parse_object *op, acpi_status status);
  88
  89static void
  90acpi_ps_link_module_code(union acpi_parse_object *parent_op,
  91                         u8 *aml_start, u32 aml_length, acpi_owner_id owner_id);
  92
  93/*******************************************************************************
  94 *
  95 * FUNCTION:    acpi_ps_get_aml_opcode
  96 *
  97 * PARAMETERS:  walk_state          - Current state
  98 *
  99 * RETURN:      Status
 100 *
 101 * DESCRIPTION: Extract the next AML opcode from the input stream.
 102 *
 103 ******************************************************************************/
 104
 105static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state)
 106{
 107
 108        ACPI_FUNCTION_TRACE_PTR(ps_get_aml_opcode, walk_state);
 109
 110        walk_state->aml_offset =
 111            (u32) ACPI_PTR_DIFF(walk_state->parser_state.aml,
 112                                walk_state->parser_state.aml_start);
 113        walk_state->opcode = acpi_ps_peek_opcode(&(walk_state->parser_state));
 114
 115        /*
 116         * First cut to determine what we have found:
 117         * 1) A valid AML opcode
 118         * 2) A name string
 119         * 3) An unknown/invalid opcode
 120         */
 121        walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode);
 122
 123        switch (walk_state->op_info->class) {
 124        case AML_CLASS_ASCII:
 125        case AML_CLASS_PREFIX:
 126                /*
 127                 * Starts with a valid prefix or ASCII char, this is a name
 128                 * string. Convert the bare name string to a namepath.
 129                 */
 130                walk_state->opcode = AML_INT_NAMEPATH_OP;
 131                walk_state->arg_types = ARGP_NAMESTRING;
 132                break;
 133
 134        case AML_CLASS_UNKNOWN:
 135
 136                /* The opcode is unrecognized. Complain and skip unknown opcodes */
 137
 138                if (walk_state->pass_number == 2) {
 139                        ACPI_ERROR((AE_INFO,
 140                                    "Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring",
 141                                    walk_state->opcode,
 142                                    (u32)(walk_state->aml_offset +
 143                                          sizeof(struct acpi_table_header))));
 144
 145                        ACPI_DUMP_BUFFER(walk_state->parser_state.aml - 16, 48);
 146
 147#ifdef ACPI_ASL_COMPILER
 148                        /*
 149                         * This is executed for the disassembler only. Output goes
 150                         * to the disassembled ASL output file.
 151                         */
 152                        acpi_os_printf
 153                            ("/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n",
 154                             walk_state->opcode,
 155                             (u32)(walk_state->aml_offset +
 156                                   sizeof(struct acpi_table_header)));
 157
 158                        /* Dump the context surrounding the invalid opcode */
 159
 160                        acpi_ut_dump_buffer(((u8 *)walk_state->parser_state.
 161                                             aml - 16), 48, DB_BYTE_DISPLAY,
 162                                            walk_state->aml_offset +
 163                                            sizeof(struct acpi_table_header) -
 164                                            16);
 165                        acpi_os_printf(" */\n");
 166#endif
 167                }
 168
 169                /* Increment past one-byte or two-byte opcode */
 170
 171                walk_state->parser_state.aml++;
 172                if (walk_state->opcode > 0xFF) {        /* Can only happen if first byte is 0x5B */
 173                        walk_state->parser_state.aml++;
 174                }
 175
 176                return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE);
 177
 178        default:
 179
 180                /* Found opcode info, this is a normal opcode */
 181
 182                walk_state->parser_state.aml +=
 183                    acpi_ps_get_opcode_size(walk_state->opcode);
 184                walk_state->arg_types = walk_state->op_info->parse_args;
 185                break;
 186        }
 187
 188        return_ACPI_STATUS(AE_OK);
 189}
 190
 191/*******************************************************************************
 192 *
 193 * FUNCTION:    acpi_ps_build_named_op
 194 *
 195 * PARAMETERS:  walk_state          - Current state
 196 *              aml_op_start        - Begin of named Op in AML
 197 *              unnamed_op          - Early Op (not a named Op)
 198 *              op                  - Returned Op
 199 *
 200 * RETURN:      Status
 201 *
 202 * DESCRIPTION: Parse a named Op
 203 *
 204 ******************************************************************************/
 205
 206static acpi_status
 207acpi_ps_build_named_op(struct acpi_walk_state *walk_state,
 208                       u8 * aml_op_start,
 209                       union acpi_parse_object *unnamed_op,
 210                       union acpi_parse_object **op)
 211{
 212        acpi_status status = AE_OK;
 213        union acpi_parse_object *arg = NULL;
 214
 215        ACPI_FUNCTION_TRACE_PTR(ps_build_named_op, walk_state);
 216
 217        unnamed_op->common.value.arg = NULL;
 218        unnamed_op->common.arg_list_length = 0;
 219        unnamed_op->common.aml_opcode = walk_state->opcode;
 220
 221        /*
 222         * Get and append arguments until we find the node that contains
 223         * the name (the type ARGP_NAME).
 224         */
 225        while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) &&
 226               (GET_CURRENT_ARG_TYPE(walk_state->arg_types) != ARGP_NAME)) {
 227                status =
 228                    acpi_ps_get_next_arg(walk_state,
 229                                         &(walk_state->parser_state),
 230                                         GET_CURRENT_ARG_TYPE(walk_state->
 231                                                              arg_types), &arg);
 232                if (ACPI_FAILURE(status)) {
 233                        return_ACPI_STATUS(status);
 234                }
 235
 236                acpi_ps_append_arg(unnamed_op, arg);
 237                INCREMENT_ARG_LIST(walk_state->arg_types);
 238        }
 239
 240        /*
 241         * Make sure that we found a NAME and didn't run out of arguments
 242         */
 243        if (!GET_CURRENT_ARG_TYPE(walk_state->arg_types)) {
 244                return_ACPI_STATUS(AE_AML_NO_OPERAND);
 245        }
 246
 247        /* We know that this arg is a name, move to next arg */
 248
 249        INCREMENT_ARG_LIST(walk_state->arg_types);
 250
 251        /*
 252         * Find the object. This will either insert the object into
 253         * the namespace or simply look it up
 254         */
 255        walk_state->op = NULL;
 256
 257        status = walk_state->descending_callback(walk_state, op);
 258        if (ACPI_FAILURE(status)) {
 259                ACPI_EXCEPTION((AE_INFO, status, "During name lookup/catalog"));
 260                return_ACPI_STATUS(status);
 261        }
 262
 263        if (!*op) {
 264                return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE);
 265        }
 266
 267        status = acpi_ps_next_parse_state(walk_state, *op, status);
 268        if (ACPI_FAILURE(status)) {
 269                if (status == AE_CTRL_PENDING) {
 270                        return_ACPI_STATUS(AE_CTRL_PARSE_PENDING);
 271                }
 272                return_ACPI_STATUS(status);
 273        }
 274
 275        acpi_ps_append_arg(*op, unnamed_op->common.value.arg);
 276        acpi_gbl_depth++;
 277
 278        if ((*op)->common.aml_opcode == AML_REGION_OP ||
 279            (*op)->common.aml_opcode == AML_DATA_REGION_OP) {
 280                /*
 281                 * Defer final parsing of an operation_region body, because we don't
 282                 * have enough info in the first pass to parse it correctly (i.e.,
 283                 * there may be method calls within the term_arg elements of the body.)
 284                 *
 285                 * However, we must continue parsing because the opregion is not a
 286                 * standalone package -- we don't know where the end is at this point.
 287                 *
 288                 * (Length is unknown until parse of the body complete)
 289                 */
 290                (*op)->named.data = aml_op_start;
 291                (*op)->named.length = 0;
 292        }
 293
 294        return_ACPI_STATUS(AE_OK);
 295}
 296
 297/*******************************************************************************
 298 *
 299 * FUNCTION:    acpi_ps_create_op
 300 *
 301 * PARAMETERS:  walk_state          - Current state
 302 *              aml_op_start        - Op start in AML
 303 *              new_op              - Returned Op
 304 *
 305 * RETURN:      Status
 306 *
 307 * DESCRIPTION: Get Op from AML
 308 *
 309 ******************************************************************************/
 310
 311static acpi_status
 312acpi_ps_create_op(struct acpi_walk_state *walk_state,
 313                  u8 * aml_op_start, union acpi_parse_object **new_op)
 314{
 315        acpi_status status = AE_OK;
 316        union acpi_parse_object *op;
 317        union acpi_parse_object *named_op = NULL;
 318        union acpi_parse_object *parent_scope;
 319        u8 argument_count;
 320        const struct acpi_opcode_info *op_info;
 321
 322        ACPI_FUNCTION_TRACE_PTR(ps_create_op, walk_state);
 323
 324        status = acpi_ps_get_aml_opcode(walk_state);
 325        if (status == AE_CTRL_PARSE_CONTINUE) {
 326                return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE);
 327        }
 328
 329        /* Create Op structure and append to parent's argument list */
 330
 331        walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode);
 332        op = acpi_ps_alloc_op(walk_state->opcode);
 333        if (!op) {
 334                return_ACPI_STATUS(AE_NO_MEMORY);
 335        }
 336
 337        if (walk_state->op_info->flags & AML_NAMED) {
 338                status =
 339                    acpi_ps_build_named_op(walk_state, aml_op_start, op,
 340                                           &named_op);
 341                acpi_ps_free_op(op);
 342                if (ACPI_FAILURE(status)) {
 343                        return_ACPI_STATUS(status);
 344                }
 345
 346                *new_op = named_op;
 347                return_ACPI_STATUS(AE_OK);
 348        }
 349
 350        /* Not a named opcode, just allocate Op and append to parent */
 351
 352        if (walk_state->op_info->flags & AML_CREATE) {
 353                /*
 354                 * Backup to beginning of create_XXXfield declaration
 355                 * body_length is unknown until we parse the body
 356                 */
 357                op->named.data = aml_op_start;
 358                op->named.length = 0;
 359        }
 360
 361        if (walk_state->opcode == AML_BANK_FIELD_OP) {
 362                /*
 363                 * Backup to beginning of bank_field declaration
 364                 * body_length is unknown until we parse the body
 365                 */
 366                op->named.data = aml_op_start;
 367                op->named.length = 0;
 368        }
 369
 370        parent_scope = acpi_ps_get_parent_scope(&(walk_state->parser_state));
 371        acpi_ps_append_arg(parent_scope, op);
 372
 373        if (parent_scope) {
 374                op_info =
 375                    acpi_ps_get_opcode_info(parent_scope->common.aml_opcode);
 376                if (op_info->flags & AML_HAS_TARGET) {
 377                        argument_count =
 378                            acpi_ps_get_argument_count(op_info->type);
 379                        if (parent_scope->common.arg_list_length >
 380                            argument_count) {
 381                                op->common.flags |= ACPI_PARSEOP_TARGET;
 382                        }
 383                } else if (parent_scope->common.aml_opcode == AML_INCREMENT_OP) {
 384                        op->common.flags |= ACPI_PARSEOP_TARGET;
 385                }
 386        }
 387
 388        if (walk_state->descending_callback != NULL) {
 389                /*
 390                 * Find the object. This will either insert the object into
 391                 * the namespace or simply look it up
 392                 */
 393                walk_state->op = *new_op = op;
 394
 395                status = walk_state->descending_callback(walk_state, &op);
 396                status = acpi_ps_next_parse_state(walk_state, op, status);
 397                if (status == AE_CTRL_PENDING) {
 398                        status = AE_CTRL_PARSE_PENDING;
 399                }
 400        }
 401
 402        return_ACPI_STATUS(status);
 403}
 404
 405/*******************************************************************************
 406 *
 407 * FUNCTION:    acpi_ps_get_arguments
 408 *
 409 * PARAMETERS:  walk_state          - Current state
 410 *              aml_op_start        - Op start in AML
 411 *              op                  - Current Op
 412 *
 413 * RETURN:      Status
 414 *
 415 * DESCRIPTION: Get arguments for passed Op.
 416 *
 417 ******************************************************************************/
 418
 419static acpi_status
 420acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
 421                      u8 * aml_op_start, union acpi_parse_object *op)
 422{
 423        acpi_status status = AE_OK;
 424        union acpi_parse_object *arg = NULL;
 425        const struct acpi_opcode_info *op_info;
 426
 427        ACPI_FUNCTION_TRACE_PTR(ps_get_arguments, walk_state);
 428
 429        switch (op->common.aml_opcode) {
 430        case AML_BYTE_OP:       /* AML_BYTEDATA_ARG */
 431        case AML_WORD_OP:       /* AML_WORDDATA_ARG */
 432        case AML_DWORD_OP:      /* AML_DWORDATA_ARG */
 433        case AML_QWORD_OP:      /* AML_QWORDATA_ARG */
 434        case AML_STRING_OP:     /* AML_ASCIICHARLIST_ARG */
 435
 436                /* Fill in constant or string argument directly */
 437
 438                acpi_ps_get_next_simple_arg(&(walk_state->parser_state),
 439                                            GET_CURRENT_ARG_TYPE(walk_state->
 440                                                                 arg_types),
 441                                            op);
 442                break;
 443
 444        case AML_INT_NAMEPATH_OP:       /* AML_NAMESTRING_ARG */
 445
 446                status =
 447                    acpi_ps_get_next_namepath(walk_state,
 448                                              &(walk_state->parser_state), op,
 449                                              1);
 450                if (ACPI_FAILURE(status)) {
 451                        return_ACPI_STATUS(status);
 452                }
 453
 454                walk_state->arg_types = 0;
 455                break;
 456
 457        default:
 458                /*
 459                 * Op is not a constant or string, append each argument to the Op
 460                 */
 461                while (GET_CURRENT_ARG_TYPE(walk_state->arg_types)
 462                       && !walk_state->arg_count) {
 463                        walk_state->aml_offset =
 464                            (u32) ACPI_PTR_DIFF(walk_state->parser_state.aml,
 465                                                walk_state->parser_state.
 466                                                aml_start);
 467
 468                        status =
 469                            acpi_ps_get_next_arg(walk_state,
 470                                                 &(walk_state->parser_state),
 471                                                 GET_CURRENT_ARG_TYPE
 472                                                 (walk_state->arg_types), &arg);
 473                        if (ACPI_FAILURE(status)) {
 474                                return_ACPI_STATUS(status);
 475                        }
 476
 477                        if (arg) {
 478                                arg->common.aml_offset = walk_state->aml_offset;
 479                                acpi_ps_append_arg(op, arg);
 480                        }
 481
 482                        INCREMENT_ARG_LIST(walk_state->arg_types);
 483                }
 484
 485                /*
 486                 * Handle executable code at "module-level". This refers to
 487                 * executable opcodes that appear outside of any control method.
 488                 */
 489                if ((walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2) &&
 490                    ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) == 0)) {
 491                        /*
 492                         * We want to skip If/Else/While constructs during Pass1 because we
 493                         * want to actually conditionally execute the code during Pass2.
 494                         *
 495                         * Except for disassembly, where we always want to walk the
 496                         * If/Else/While packages
 497                         */
 498                        switch (op->common.aml_opcode) {
 499                        case AML_IF_OP:
 500                        case AML_ELSE_OP:
 501                        case AML_WHILE_OP:
 502
 503                                /*
 504                                 * Currently supported module-level opcodes are:
 505                                 * IF/ELSE/WHILE. These appear to be the most common,
 506                                 * and easiest to support since they open an AML
 507                                 * package.
 508                                 */
 509                                if (walk_state->pass_number ==
 510                                    ACPI_IMODE_LOAD_PASS1) {
 511                                        acpi_ps_link_module_code(op->common.
 512                                                                 parent,
 513                                                                 aml_op_start,
 514                                                                 (u32)
 515                                                                 (walk_state->
 516                                                                 parser_state.
 517                                                                 pkg_end -
 518                                                                 aml_op_start),
 519                                                                 walk_state->
 520                                                                 owner_id);
 521                                }
 522
 523                                ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
 524                                                  "Pass1: Skipping an If/Else/While body\n"));
 525
 526                                /* Skip body of if/else/while in pass 1 */
 527
 528                                walk_state->parser_state.aml =
 529                                    walk_state->parser_state.pkg_end;
 530                                walk_state->arg_count = 0;
 531                                break;
 532
 533                        default:
 534                                /*
 535                                 * Check for an unsupported executable opcode at module
 536                                 * level. We must be in PASS1, the parent must be a SCOPE,
 537                                 * The opcode class must be EXECUTE, and the opcode must
 538                                 * not be an argument to another opcode.
 539                                 */
 540                                if ((walk_state->pass_number ==
 541                                     ACPI_IMODE_LOAD_PASS1)
 542                                    && (op->common.parent->common.aml_opcode ==
 543                                        AML_SCOPE_OP)) {
 544                                        op_info =
 545                                            acpi_ps_get_opcode_info(op->common.
 546                                                                    aml_opcode);
 547                                        if ((op_info->class ==
 548                                             AML_CLASS_EXECUTE) && (!arg)) {
 549                                                ACPI_WARNING((AE_INFO,
 550                                                              "Unsupported module-level executable opcode "
 551                                                              "0x%.2X at table offset 0x%.4X",
 552                                                              op->common.
 553                                                              aml_opcode,
 554                                                              (u32)
 555                                                              (ACPI_PTR_DIFF
 556                                                               (aml_op_start,
 557                                                                walk_state->
 558                                                                parser_state.
 559                                                                aml_start) +
 560                                                               sizeof(struct
 561                                                                      acpi_table_header))));
 562                                        }
 563                                }
 564                                break;
 565                        }
 566                }
 567
 568                /* Special processing for certain opcodes */
 569
 570                switch (op->common.aml_opcode) {
 571                case AML_METHOD_OP:
 572                        /*
 573                         * Skip parsing of control method because we don't have enough
 574                         * info in the first pass to parse it correctly.
 575                         *
 576                         * Save the length and address of the body
 577                         */
 578                        op->named.data = walk_state->parser_state.aml;
 579                        op->named.length = (u32)
 580                            (walk_state->parser_state.pkg_end -
 581                             walk_state->parser_state.aml);
 582
 583                        /* Skip body of method */
 584
 585                        walk_state->parser_state.aml =
 586                            walk_state->parser_state.pkg_end;
 587                        walk_state->arg_count = 0;
 588                        break;
 589
 590                case AML_BUFFER_OP:
 591                case AML_PACKAGE_OP:
 592                case AML_VAR_PACKAGE_OP:
 593
 594                        if ((op->common.parent) &&
 595                            (op->common.parent->common.aml_opcode ==
 596                             AML_NAME_OP)
 597                            && (walk_state->pass_number <=
 598                                ACPI_IMODE_LOAD_PASS2)) {
 599                                /*
 600                                 * Skip parsing of Buffers and Packages because we don't have
 601                                 * enough info in the first pass to parse them correctly.
 602                                 */
 603                                op->named.data = aml_op_start;
 604                                op->named.length = (u32)
 605                                    (walk_state->parser_state.pkg_end -
 606                                     aml_op_start);
 607
 608                                /* Skip body */
 609
 610                                walk_state->parser_state.aml =
 611                                    walk_state->parser_state.pkg_end;
 612                                walk_state->arg_count = 0;
 613                        }
 614                        break;
 615
 616                case AML_WHILE_OP:
 617
 618                        if (walk_state->control_state) {
 619                                walk_state->control_state->control.package_end =
 620                                    walk_state->parser_state.pkg_end;
 621                        }
 622                        break;
 623
 624                default:
 625
 626                        /* No action for all other opcodes */
 627                        break;
 628                }
 629
 630                break;
 631        }
 632
 633        return_ACPI_STATUS(AE_OK);
 634}
 635
 636/*******************************************************************************
 637 *
 638 * FUNCTION:    acpi_ps_link_module_code
 639 *
 640 * PARAMETERS:  parent_op           - Parent parser op
 641 *              aml_start           - Pointer to the AML
 642 *              aml_length          - Length of executable AML
 643 *              owner_id            - owner_id of module level code
 644 *
 645 * RETURN:      None.
 646 *
 647 * DESCRIPTION: Wrap the module-level code with a method object and link the
 648 *              object to the global list. Note, the mutex field of the method
 649 *              object is used to link multiple module-level code objects.
 650 *
 651 ******************************************************************************/
 652
 653static void
 654acpi_ps_link_module_code(union acpi_parse_object *parent_op,
 655                         u8 *aml_start, u32 aml_length, acpi_owner_id owner_id)
 656{
 657        union acpi_operand_object *prev;
 658        union acpi_operand_object *next;
 659        union acpi_operand_object *method_obj;
 660        struct acpi_namespace_node *parent_node;
 661
 662        /* Get the tail of the list */
 663
 664        prev = next = acpi_gbl_module_code_list;
 665        while (next) {
 666                prev = next;
 667                next = next->method.mutex;
 668        }
 669
 670        /*
 671         * Insert the module level code into the list. Merge it if it is
 672         * adjacent to the previous element.
 673         */
 674        if (!prev ||
 675            ((prev->method.aml_start + prev->method.aml_length) != aml_start)) {
 676
 677                /* Create, initialize, and link a new temporary method object */
 678
 679                method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
 680                if (!method_obj) {
 681                        return;
 682                }
 683
 684                if (parent_op->common.node) {
 685                        parent_node = parent_op->common.node;
 686                } else {
 687                        parent_node = acpi_gbl_root_node;
 688                }
 689
 690                method_obj->method.aml_start = aml_start;
 691                method_obj->method.aml_length = aml_length;
 692                method_obj->method.owner_id = owner_id;
 693                method_obj->method.info_flags |= ACPI_METHOD_MODULE_LEVEL;
 694
 695                /*
 696                 * Save the parent node in next_object. This is cheating, but we
 697                 * don't want to expand the method object.
 698                 */
 699                method_obj->method.next_object =
 700                    ACPI_CAST_PTR(union acpi_operand_object, parent_node);
 701
 702                if (!prev) {
 703                        acpi_gbl_module_code_list = method_obj;
 704                } else {
 705                        prev->method.mutex = method_obj;
 706                }
 707        } else {
 708                prev->method.aml_length += aml_length;
 709        }
 710}
 711
 712/*******************************************************************************
 713 *
 714 * FUNCTION:    acpi_ps_complete_op
 715 *
 716 * PARAMETERS:  walk_state          - Current state
 717 *              op                  - Returned Op
 718 *              status              - Parse status before complete Op
 719 *
 720 * RETURN:      Status
 721 *
 722 * DESCRIPTION: Complete Op
 723 *
 724 ******************************************************************************/
 725
 726static acpi_status
 727acpi_ps_complete_op(struct acpi_walk_state *walk_state,
 728                    union acpi_parse_object **op, acpi_status status)
 729{
 730        acpi_status status2;
 731
 732        ACPI_FUNCTION_TRACE_PTR(ps_complete_op, walk_state);
 733
 734        /*
 735         * Finished one argument of the containing scope
 736         */
 737        walk_state->parser_state.scope->parse_scope.arg_count--;
 738
 739        /* Close this Op (will result in parse subtree deletion) */
 740
 741        status2 = acpi_ps_complete_this_op(walk_state, *op);
 742        if (ACPI_FAILURE(status2)) {
 743                return_ACPI_STATUS(status2);
 744        }
 745
 746        *op = NULL;
 747
 748        switch (status) {
 749        case AE_OK:
 750                break;
 751
 752        case AE_CTRL_TRANSFER:
 753
 754                /* We are about to transfer to a called method */
 755
 756                walk_state->prev_op = NULL;
 757                walk_state->prev_arg_types = walk_state->arg_types;
 758                return_ACPI_STATUS(status);
 759
 760        case AE_CTRL_END:
 761
 762                acpi_ps_pop_scope(&(walk_state->parser_state), op,
 763                                  &walk_state->arg_types,
 764                                  &walk_state->arg_count);
 765
 766                if (*op) {
 767                        walk_state->op = *op;
 768                        walk_state->op_info =
 769                            acpi_ps_get_opcode_info((*op)->common.aml_opcode);
 770                        walk_state->opcode = (*op)->common.aml_opcode;
 771
 772                        status = walk_state->ascending_callback(walk_state);
 773                        status =
 774                            acpi_ps_next_parse_state(walk_state, *op, status);
 775
 776                        status2 = acpi_ps_complete_this_op(walk_state, *op);
 777                        if (ACPI_FAILURE(status2)) {
 778                                return_ACPI_STATUS(status2);
 779                        }
 780                }
 781
 782                status = AE_OK;
 783                break;
 784
 785        case AE_CTRL_BREAK:
 786        case AE_CTRL_CONTINUE:
 787
 788                /* Pop off scopes until we find the While */
 789
 790                while (!(*op) || ((*op)->common.aml_opcode != AML_WHILE_OP)) {
 791                        acpi_ps_pop_scope(&(walk_state->parser_state), op,
 792                                          &walk_state->arg_types,
 793                                          &walk_state->arg_count);
 794                }
 795
 796                /* Close this iteration of the While loop */
 797
 798                walk_state->op = *op;
 799                walk_state->op_info =
 800                    acpi_ps_get_opcode_info((*op)->common.aml_opcode);
 801                walk_state->opcode = (*op)->common.aml_opcode;
 802
 803                status = walk_state->ascending_callback(walk_state);
 804                status = acpi_ps_next_parse_state(walk_state, *op, status);
 805
 806                status2 = acpi_ps_complete_this_op(walk_state, *op);
 807                if (ACPI_FAILURE(status2)) {
 808                        return_ACPI_STATUS(status2);
 809                }
 810
 811                status = AE_OK;
 812                break;
 813
 814        case AE_CTRL_TERMINATE:
 815
 816                /* Clean up */
 817                do {
 818                        if (*op) {
 819                                status2 =
 820                                    acpi_ps_complete_this_op(walk_state, *op);
 821                                if (ACPI_FAILURE(status2)) {
 822                                        return_ACPI_STATUS(status2);
 823                                }
 824
 825                                acpi_ut_delete_generic_state
 826                                    (acpi_ut_pop_generic_state
 827                                     (&walk_state->control_state));
 828                        }
 829
 830                        acpi_ps_pop_scope(&(walk_state->parser_state), op,
 831                                          &walk_state->arg_types,
 832                                          &walk_state->arg_count);
 833
 834                } while (*op);
 835
 836                return_ACPI_STATUS(AE_OK);
 837
 838        default:                /* All other non-AE_OK status */
 839
 840                do {
 841                        if (*op) {
 842                                status2 =
 843                                    acpi_ps_complete_this_op(walk_state, *op);
 844                                if (ACPI_FAILURE(status2)) {
 845                                        return_ACPI_STATUS(status2);
 846                                }
 847                        }
 848
 849                        acpi_ps_pop_scope(&(walk_state->parser_state), op,
 850                                          &walk_state->arg_types,
 851                                          &walk_state->arg_count);
 852
 853                } while (*op);
 854
 855#if 0
 856                /*
 857                 * TBD: Cleanup parse ops on error
 858                 */
 859                if (*op == NULL) {
 860                        acpi_ps_pop_scope(parser_state, op,
 861                                          &walk_state->arg_types,
 862                                          &walk_state->arg_count);
 863                }
 864#endif
 865                walk_state->prev_op = NULL;
 866                walk_state->prev_arg_types = walk_state->arg_types;
 867                return_ACPI_STATUS(status);
 868        }
 869
 870        /* This scope complete? */
 871
 872        if (acpi_ps_has_completed_scope(&(walk_state->parser_state))) {
 873                acpi_ps_pop_scope(&(walk_state->parser_state), op,
 874                                  &walk_state->arg_types,
 875                                  &walk_state->arg_count);
 876                ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *op));
 877        } else {
 878                *op = NULL;
 879        }
 880
 881        return_ACPI_STATUS(AE_OK);
 882}
 883
 884/*******************************************************************************
 885 *
 886 * FUNCTION:    acpi_ps_complete_final_op
 887 *
 888 * PARAMETERS:  walk_state          - Current state
 889 *              op                  - Current Op
 890 *              status              - Current parse status before complete last
 891 *                                    Op
 892 *
 893 * RETURN:      Status
 894 *
 895 * DESCRIPTION: Complete last Op.
 896 *
 897 ******************************************************************************/
 898
 899static acpi_status
 900acpi_ps_complete_final_op(struct acpi_walk_state *walk_state,
 901                          union acpi_parse_object *op, acpi_status status)
 902{
 903        acpi_status status2;
 904
 905        ACPI_FUNCTION_TRACE_PTR(ps_complete_final_op, walk_state);
 906
 907        /*
 908         * Complete the last Op (if not completed), and clear the scope stack.
 909         * It is easily possible to end an AML "package" with an unbounded number
 910         * of open scopes (such as when several ASL blocks are closed with
 911         * sequential closing braces). We want to terminate each one cleanly.
 912         */
 913        ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "AML package complete at Op %p\n",
 914                          op));
 915        do {
 916                if (op) {
 917                        if (walk_state->ascending_callback != NULL) {
 918                                walk_state->op = op;
 919                                walk_state->op_info =
 920                                    acpi_ps_get_opcode_info(op->common.
 921                                                            aml_opcode);
 922                                walk_state->opcode = op->common.aml_opcode;
 923
 924                                status =
 925                                    walk_state->ascending_callback(walk_state);
 926                                status =
 927                                    acpi_ps_next_parse_state(walk_state, op,
 928                                                             status);
 929                                if (status == AE_CTRL_PENDING) {
 930                                        status =
 931                                            acpi_ps_complete_op(walk_state, &op,
 932                                                                AE_OK);
 933                                        if (ACPI_FAILURE(status)) {
 934                                                return_ACPI_STATUS(status);
 935                                        }
 936                                }
 937
 938                                if (status == AE_CTRL_TERMINATE) {
 939                                        status = AE_OK;
 940
 941                                        /* Clean up */
 942                                        do {
 943                                                if (op) {
 944                                                        status2 =
 945                                                            acpi_ps_complete_this_op
 946                                                            (walk_state, op);
 947                                                        if (ACPI_FAILURE
 948                                                            (status2)) {
 949                                                                return_ACPI_STATUS
 950                                                                    (status2);
 951                                                        }
 952                                                }
 953
 954                                                acpi_ps_pop_scope(&
 955                                                                  (walk_state->
 956                                                                   parser_state),
 957                                                                  &op,
 958                                                                  &walk_state->
 959                                                                  arg_types,
 960                                                                  &walk_state->
 961                                                                  arg_count);
 962
 963                                        } while (op);
 964
 965                                        return_ACPI_STATUS(status);
 966                                }
 967
 968                                else if (ACPI_FAILURE(status)) {
 969
 970                                        /* First error is most important */
 971
 972                                        (void)
 973                                            acpi_ps_complete_this_op(walk_state,
 974                                                                     op);
 975                                        return_ACPI_STATUS(status);
 976                                }
 977                        }
 978
 979                        status2 = acpi_ps_complete_this_op(walk_state, op);
 980                        if (ACPI_FAILURE(status2)) {
 981                                return_ACPI_STATUS(status2);
 982                        }
 983                }
 984
 985                acpi_ps_pop_scope(&(walk_state->parser_state), &op,
 986                                  &walk_state->arg_types,
 987                                  &walk_state->arg_count);
 988
 989        } while (op);
 990
 991        return_ACPI_STATUS(status);
 992}
 993
 994/*******************************************************************************
 995 *
 996 * FUNCTION:    acpi_ps_parse_loop
 997 *
 998 * PARAMETERS:  walk_state          - Current state
 999 *
1000 * RETURN:      Status
1001 *
1002 * DESCRIPTION: Parse AML (pointed to by the current parser state) and return
1003 *              a tree of ops.
1004 *
1005 ******************************************************************************/
1006
1007acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
1008{
1009        acpi_status status = AE_OK;
1010        union acpi_parse_object *op = NULL;     /* current op */
1011        struct acpi_parse_state *parser_state;
1012        u8 *aml_op_start = NULL;
1013
1014        ACPI_FUNCTION_TRACE_PTR(ps_parse_loop, walk_state);
1015
1016        if (walk_state->descending_callback == NULL) {
1017                return_ACPI_STATUS(AE_BAD_PARAMETER);
1018        }
1019
1020        parser_state = &walk_state->parser_state;
1021        walk_state->arg_types = 0;
1022
1023#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
1024
1025        if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) {
1026
1027                /* We are restarting a preempted control method */
1028
1029                if (acpi_ps_has_completed_scope(parser_state)) {
1030                        /*
1031                         * We must check if a predicate to an IF or WHILE statement
1032                         * was just completed
1033                         */
1034                        if ((parser_state->scope->parse_scope.op) &&
1035                            ((parser_state->scope->parse_scope.op->common.
1036                              aml_opcode == AML_IF_OP)
1037                             || (parser_state->scope->parse_scope.op->common.
1038                                 aml_opcode == AML_WHILE_OP))
1039                            && (walk_state->control_state)
1040                            && (walk_state->control_state->common.state ==
1041                                ACPI_CONTROL_PREDICATE_EXECUTING)) {
1042                                /*
1043                                 * A predicate was just completed, get the value of the
1044                                 * predicate and branch based on that value
1045                                 */
1046                                walk_state->op = NULL;
1047                                status =
1048                                    acpi_ds_get_predicate_value(walk_state,
1049                                                                ACPI_TO_POINTER
1050                                                                (TRUE));
1051                                if (ACPI_FAILURE(status)
1052                                    && ((status & AE_CODE_MASK) !=
1053                                        AE_CODE_CONTROL)) {
1054                                        if (status == AE_AML_NO_RETURN_VALUE) {
1055                                                ACPI_EXCEPTION((AE_INFO, status,
1056                                                                "Invoked method did not return a value"));
1057                                        }
1058
1059                                        ACPI_EXCEPTION((AE_INFO, status,
1060                                                        "GetPredicate Failed"));
1061                                        return_ACPI_STATUS(status);
1062                                }
1063
1064                                status =
1065                                    acpi_ps_next_parse_state(walk_state, op,
1066                                                             status);
1067                        }
1068
1069                        acpi_ps_pop_scope(parser_state, &op,
1070                                          &walk_state->arg_types,
1071                                          &walk_state->arg_count);
1072                        ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
1073                                          "Popped scope, Op=%p\n", op));
1074                } else if (walk_state->prev_op) {
1075
1076                        /* We were in the middle of an op */
1077
1078                        op = walk_state->prev_op;
1079                        walk_state->arg_types = walk_state->prev_arg_types;
1080                }
1081        }
1082#endif
1083
1084        /* Iterative parsing loop, while there is more AML to process: */
1085
1086        while ((parser_state->aml < parser_state->aml_end) || (op)) {
1087                aml_op_start = parser_state->aml;
1088                if (!op) {
1089                        status =
1090                            acpi_ps_create_op(walk_state, aml_op_start, &op);
1091                        if (ACPI_FAILURE(status)) {
1092                                if (status == AE_CTRL_PARSE_CONTINUE) {
1093                                        continue;
1094                                }
1095
1096                                if (status == AE_CTRL_PARSE_PENDING) {
1097                                        status = AE_OK;
1098                                }
1099
1100                                status =
1101                                    acpi_ps_complete_op(walk_state, &op,
1102                                                        status);
1103                                if (ACPI_FAILURE(status)) {
1104                                        return_ACPI_STATUS(status);
1105                                }
1106
1107                                continue;
1108                        }
1109
1110                        op->common.aml_offset = walk_state->aml_offset;
1111
1112                        if (walk_state->op_info) {
1113                                ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
1114                                                  "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n",
1115                                                  (u32) op->common.aml_opcode,
1116                                                  walk_state->op_info->name, op,
1117                                                  parser_state->aml,
1118                                                  op->common.aml_offset));
1119                        }
1120                }
1121
1122                /*
1123                 * Start arg_count at zero because we don't know if there are
1124                 * any args yet
1125                 */
1126                walk_state->arg_count = 0;
1127
1128                /* Are there any arguments that must be processed? */
1129
1130                if (walk_state->arg_types) {
1131
1132                        /* Get arguments */
1133
1134                        status =
1135                            acpi_ps_get_arguments(walk_state, aml_op_start, op);
1136                        if (ACPI_FAILURE(status)) {
1137                                status =
1138                                    acpi_ps_complete_op(walk_state, &op,
1139                                                        status);
1140                                if (ACPI_FAILURE(status)) {
1141                                        return_ACPI_STATUS(status);
1142                                }
1143
1144                                continue;
1145                        }
1146                }
1147
1148                /* Check for arguments that need to be processed */
1149
1150                if (walk_state->arg_count) {
1151                        /*
1152                         * There are arguments (complex ones), push Op and
1153                         * prepare for argument
1154                         */
1155                        status = acpi_ps_push_scope(parser_state, op,
1156                                                    walk_state->arg_types,
1157                                                    walk_state->arg_count);
1158                        if (ACPI_FAILURE(status)) {
1159                                status =
1160                                    acpi_ps_complete_op(walk_state, &op,
1161                                                        status);
1162                                if (ACPI_FAILURE(status)) {
1163                                        return_ACPI_STATUS(status);
1164                                }
1165
1166                                continue;
1167                        }
1168
1169                        op = NULL;
1170                        continue;
1171                }
1172
1173                /*
1174                 * All arguments have been processed -- Op is complete,
1175                 * prepare for next
1176                 */
1177                walk_state->op_info =
1178                    acpi_ps_get_opcode_info(op->common.aml_opcode);
1179                if (walk_state->op_info->flags & AML_NAMED) {
1180                        if (acpi_gbl_depth) {
1181                                acpi_gbl_depth--;
1182                        }
1183
1184                        if (op->common.aml_opcode == AML_REGION_OP ||
1185                            op->common.aml_opcode == AML_DATA_REGION_OP) {
1186                                /*
1187                                 * Skip parsing of control method or opregion body,
1188                                 * because we don't have enough info in the first pass
1189                                 * to parse them correctly.
1190                                 *
1191                                 * Completed parsing an op_region declaration, we now
1192                                 * know the length.
1193                                 */
1194                                op->named.length =
1195                                    (u32) (parser_state->aml - op->named.data);
1196                        }
1197                }
1198
1199                if (walk_state->op_info->flags & AML_CREATE) {
1200                        /*
1201                         * Backup to beginning of create_XXXfield declaration (1 for
1202                         * Opcode)
1203                         *
1204                         * body_length is unknown until we parse the body
1205                         */
1206                        op->named.length =
1207                            (u32) (parser_state->aml - op->named.data);
1208                }
1209
1210                if (op->common.aml_opcode == AML_BANK_FIELD_OP) {
1211                        /*
1212                         * Backup to beginning of bank_field declaration
1213                         *
1214                         * body_length is unknown until we parse the body
1215                         */
1216                        op->named.length =
1217                            (u32) (parser_state->aml - op->named.data);
1218                }
1219
1220                /* This op complete, notify the dispatcher */
1221
1222                if (walk_state->ascending_callback != NULL) {
1223                        walk_state->op = op;
1224                        walk_state->opcode = op->common.aml_opcode;
1225
1226                        status = walk_state->ascending_callback(walk_state);
1227                        status =
1228                            acpi_ps_next_parse_state(walk_state, op, status);
1229                        if (status == AE_CTRL_PENDING) {
1230                                status = AE_OK;
1231                        }
1232                }
1233
1234                status = acpi_ps_complete_op(walk_state, &op, status);
1235                if (ACPI_FAILURE(status)) {
1236                        return_ACPI_STATUS(status);
1237                }
1238
1239        }                       /* while parser_state->Aml */
1240
1241        status = acpi_ps_complete_final_op(walk_state, op, status);
1242        return_ACPI_STATUS(status);
1243}
1244