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 - 2016, 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 "acinterp.h"
  55#include "acparser.h"
  56#include "acdispat.h"
  57#include "amlcode.h"
  58
  59#define _COMPONENT          ACPI_PARSER
  60ACPI_MODULE_NAME("psloop")
  61
  62/* Local prototypes */
  63static acpi_status
  64acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
  65                      u8 * aml_op_start, union acpi_parse_object *op);
  66
  67static void
  68acpi_ps_link_module_code(union acpi_parse_object *parent_op,
  69                         u8 *aml_start, u32 aml_length, acpi_owner_id owner_id);
  70
  71/*******************************************************************************
  72 *
  73 * FUNCTION:    acpi_ps_get_arguments
  74 *
  75 * PARAMETERS:  walk_state          - Current state
  76 *              aml_op_start        - Op start in AML
  77 *              op                  - Current Op
  78 *
  79 * RETURN:      Status
  80 *
  81 * DESCRIPTION: Get arguments for passed Op.
  82 *
  83 ******************************************************************************/
  84
  85static acpi_status
  86acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
  87                      u8 * aml_op_start, union acpi_parse_object *op)
  88{
  89        acpi_status status = AE_OK;
  90        union acpi_parse_object *arg = NULL;
  91        const struct acpi_opcode_info *op_info;
  92
  93        ACPI_FUNCTION_TRACE_PTR(ps_get_arguments, walk_state);
  94
  95        switch (op->common.aml_opcode) {
  96        case AML_BYTE_OP:       /* AML_BYTEDATA_ARG */
  97        case AML_WORD_OP:       /* AML_WORDDATA_ARG */
  98        case AML_DWORD_OP:      /* AML_DWORDATA_ARG */
  99        case AML_QWORD_OP:      /* AML_QWORDATA_ARG */
 100        case AML_STRING_OP:     /* AML_ASCIICHARLIST_ARG */
 101
 102                /* Fill in constant or string argument directly */
 103
 104                acpi_ps_get_next_simple_arg(&(walk_state->parser_state),
 105                                            GET_CURRENT_ARG_TYPE(walk_state->
 106                                                                 arg_types),
 107                                            op);
 108                break;
 109
 110        case AML_INT_NAMEPATH_OP:       /* AML_NAMESTRING_ARG */
 111
 112                status = acpi_ps_get_next_namepath(walk_state,
 113                                                   &(walk_state->parser_state),
 114                                                   op,
 115                                                   ACPI_POSSIBLE_METHOD_CALL);
 116                if (ACPI_FAILURE(status)) {
 117                        return_ACPI_STATUS(status);
 118                }
 119
 120                walk_state->arg_types = 0;
 121                break;
 122
 123        default:
 124                /*
 125                 * Op is not a constant or string, append each argument to the Op
 126                 */
 127                while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) &&
 128                       !walk_state->arg_count) {
 129                        walk_state->aml = walk_state->parser_state.aml;
 130
 131                        status =
 132                            acpi_ps_get_next_arg(walk_state,
 133                                                 &(walk_state->parser_state),
 134                                                 GET_CURRENT_ARG_TYPE
 135                                                 (walk_state->arg_types), &arg);
 136                        if (ACPI_FAILURE(status)) {
 137                                return_ACPI_STATUS(status);
 138                        }
 139
 140                        if (arg) {
 141                                acpi_ps_append_arg(op, arg);
 142                        }
 143
 144                        INCREMENT_ARG_LIST(walk_state->arg_types);
 145                }
 146
 147                /*
 148                 * Handle executable code at "module-level". This refers to
 149                 * executable opcodes that appear outside of any control method.
 150                 */
 151                if ((walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2) &&
 152                    ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) == 0)) {
 153                        /*
 154                         * We want to skip If/Else/While constructs during Pass1 because we
 155                         * want to actually conditionally execute the code during Pass2.
 156                         *
 157                         * Except for disassembly, where we always want to walk the
 158                         * If/Else/While packages
 159                         */
 160                        switch (op->common.aml_opcode) {
 161                        case AML_IF_OP:
 162                        case AML_ELSE_OP:
 163                        case AML_WHILE_OP:
 164                                /*
 165                                 * Currently supported module-level opcodes are:
 166                                 * IF/ELSE/WHILE. These appear to be the most common,
 167                                 * and easiest to support since they open an AML
 168                                 * package.
 169                                 */
 170                                if (walk_state->pass_number ==
 171                                    ACPI_IMODE_LOAD_PASS1) {
 172                                        acpi_ps_link_module_code(op->common.
 173                                                                 parent,
 174                                                                 aml_op_start,
 175                                                                 (u32)
 176                                                                 (walk_state->
 177                                                                 parser_state.
 178                                                                 pkg_end -
 179                                                                 aml_op_start),
 180                                                                 walk_state->
 181                                                                 owner_id);
 182                                }
 183
 184                                ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
 185                                                  "Pass1: Skipping an If/Else/While body\n"));
 186
 187                                /* Skip body of if/else/while in pass 1 */
 188
 189                                walk_state->parser_state.aml =
 190                                    walk_state->parser_state.pkg_end;
 191                                walk_state->arg_count = 0;
 192                                break;
 193
 194                        default:
 195                                /*
 196                                 * Check for an unsupported executable opcode at module
 197                                 * level. We must be in PASS1, the parent must be a SCOPE,
 198                                 * The opcode class must be EXECUTE, and the opcode must
 199                                 * not be an argument to another opcode.
 200                                 */
 201                                if ((walk_state->pass_number ==
 202                                     ACPI_IMODE_LOAD_PASS1)
 203                                    && (op->common.parent->common.aml_opcode ==
 204                                        AML_SCOPE_OP)) {
 205                                        op_info =
 206                                            acpi_ps_get_opcode_info(op->common.
 207                                                                    aml_opcode);
 208                                        if ((op_info->class ==
 209                                             AML_CLASS_EXECUTE) && (!arg)) {
 210                                                ACPI_WARNING((AE_INFO,
 211                                                              "Unsupported module-level executable opcode "
 212                                                              "0x%.2X at table offset 0x%.4X",
 213                                                              op->common.
 214                                                              aml_opcode,
 215                                                              (u32)
 216                                                              (ACPI_PTR_DIFF
 217                                                               (aml_op_start,
 218                                                                walk_state->
 219                                                                parser_state.
 220                                                                aml_start) +
 221                                                               sizeof(struct
 222                                                                      acpi_table_header))));
 223                                        }
 224                                }
 225                                break;
 226                        }
 227                }
 228
 229                /* Special processing for certain opcodes */
 230
 231                switch (op->common.aml_opcode) {
 232                case AML_METHOD_OP:
 233                        /*
 234                         * Skip parsing of control method because we don't have enough
 235                         * info in the first pass to parse it correctly.
 236                         *
 237                         * Save the length and address of the body
 238                         */
 239                        op->named.data = walk_state->parser_state.aml;
 240                        op->named.length = (u32)
 241                            (walk_state->parser_state.pkg_end -
 242                             walk_state->parser_state.aml);
 243
 244                        /* Skip body of method */
 245
 246                        walk_state->parser_state.aml =
 247                            walk_state->parser_state.pkg_end;
 248                        walk_state->arg_count = 0;
 249                        break;
 250
 251                case AML_BUFFER_OP:
 252                case AML_PACKAGE_OP:
 253                case AML_VAR_PACKAGE_OP:
 254
 255                        if ((op->common.parent) &&
 256                            (op->common.parent->common.aml_opcode ==
 257                             AML_NAME_OP)
 258                            && (walk_state->pass_number <=
 259                                ACPI_IMODE_LOAD_PASS2)) {
 260                                /*
 261                                 * Skip parsing of Buffers and Packages because we don't have
 262                                 * enough info in the first pass to parse them correctly.
 263                                 */
 264                                op->named.data = aml_op_start;
 265                                op->named.length = (u32)
 266                                    (walk_state->parser_state.pkg_end -
 267                                     aml_op_start);
 268
 269                                /* Skip body */
 270
 271                                walk_state->parser_state.aml =
 272                                    walk_state->parser_state.pkg_end;
 273                                walk_state->arg_count = 0;
 274                        }
 275                        break;
 276
 277                case AML_WHILE_OP:
 278
 279                        if (walk_state->control_state) {
 280                                walk_state->control_state->control.package_end =
 281                                    walk_state->parser_state.pkg_end;
 282                        }
 283                        break;
 284
 285                default:
 286
 287                        /* No action for all other opcodes */
 288
 289                        break;
 290                }
 291
 292                break;
 293        }
 294
 295        return_ACPI_STATUS(AE_OK);
 296}
 297
 298/*******************************************************************************
 299 *
 300 * FUNCTION:    acpi_ps_link_module_code
 301 *
 302 * PARAMETERS:  parent_op           - Parent parser op
 303 *              aml_start           - Pointer to the AML
 304 *              aml_length          - Length of executable AML
 305 *              owner_id            - owner_id of module level code
 306 *
 307 * RETURN:      None.
 308 *
 309 * DESCRIPTION: Wrap the module-level code with a method object and link the
 310 *              object to the global list. Note, the mutex field of the method
 311 *              object is used to link multiple module-level code objects.
 312 *
 313 ******************************************************************************/
 314
 315static void
 316acpi_ps_link_module_code(union acpi_parse_object *parent_op,
 317                         u8 *aml_start, u32 aml_length, acpi_owner_id owner_id)
 318{
 319        union acpi_operand_object *prev;
 320        union acpi_operand_object *next;
 321        union acpi_operand_object *method_obj;
 322        struct acpi_namespace_node *parent_node;
 323
 324        ACPI_FUNCTION_TRACE(ps_link_module_code);
 325
 326        /* Get the tail of the list */
 327
 328        prev = next = acpi_gbl_module_code_list;
 329        while (next) {
 330                prev = next;
 331                next = next->method.mutex;
 332        }
 333
 334        /*
 335         * Insert the module level code into the list. Merge it if it is
 336         * adjacent to the previous element.
 337         */
 338        if (!prev ||
 339            ((prev->method.aml_start + prev->method.aml_length) != aml_start)) {
 340
 341                /* Create, initialize, and link a new temporary method object */
 342
 343                method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
 344                if (!method_obj) {
 345                        return_VOID;
 346                }
 347
 348                ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
 349                                  "Create/Link new code block: %p\n",
 350                                  method_obj));
 351
 352                if (parent_op->common.node) {
 353                        parent_node = parent_op->common.node;
 354                } else {
 355                        parent_node = acpi_gbl_root_node;
 356                }
 357
 358                method_obj->method.aml_start = aml_start;
 359                method_obj->method.aml_length = aml_length;
 360                method_obj->method.owner_id = owner_id;
 361                method_obj->method.info_flags |= ACPI_METHOD_MODULE_LEVEL;
 362
 363                /*
 364                 * Save the parent node in next_object. This is cheating, but we
 365                 * don't want to expand the method object.
 366                 */
 367                method_obj->method.next_object =
 368                    ACPI_CAST_PTR(union acpi_operand_object, parent_node);
 369
 370                if (!prev) {
 371                        acpi_gbl_module_code_list = method_obj;
 372                } else {
 373                        prev->method.mutex = method_obj;
 374                }
 375        } else {
 376                ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
 377                                  "Appending to existing code block: %p\n",
 378                                  prev));
 379
 380                prev->method.aml_length += aml_length;
 381        }
 382
 383        return_VOID;
 384}
 385
 386/*******************************************************************************
 387 *
 388 * FUNCTION:    acpi_ps_parse_loop
 389 *
 390 * PARAMETERS:  walk_state          - Current state
 391 *
 392 * RETURN:      Status
 393 *
 394 * DESCRIPTION: Parse AML (pointed to by the current parser state) and return
 395 *              a tree of ops.
 396 *
 397 ******************************************************************************/
 398
 399acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
 400{
 401        acpi_status status = AE_OK;
 402        union acpi_parse_object *op = NULL;     /* current op */
 403        struct acpi_parse_state *parser_state;
 404        u8 *aml_op_start = NULL;
 405
 406        ACPI_FUNCTION_TRACE_PTR(ps_parse_loop, walk_state);
 407
 408        if (walk_state->descending_callback == NULL) {
 409                return_ACPI_STATUS(AE_BAD_PARAMETER);
 410        }
 411
 412        parser_state = &walk_state->parser_state;
 413        walk_state->arg_types = 0;
 414
 415#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
 416
 417        if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) {
 418
 419                /* We are restarting a preempted control method */
 420
 421                if (acpi_ps_has_completed_scope(parser_state)) {
 422                        /*
 423                         * We must check if a predicate to an IF or WHILE statement
 424                         * was just completed
 425                         */
 426                        if ((parser_state->scope->parse_scope.op) &&
 427                            ((parser_state->scope->parse_scope.op->common.
 428                              aml_opcode == AML_IF_OP)
 429                             || (parser_state->scope->parse_scope.op->common.
 430                                 aml_opcode == AML_WHILE_OP))
 431                            && (walk_state->control_state)
 432                            && (walk_state->control_state->common.state ==
 433                                ACPI_CONTROL_PREDICATE_EXECUTING)) {
 434                                /*
 435                                 * A predicate was just completed, get the value of the
 436                                 * predicate and branch based on that value
 437                                 */
 438                                walk_state->op = NULL;
 439                                status =
 440                                    acpi_ds_get_predicate_value(walk_state,
 441                                                                ACPI_TO_POINTER
 442                                                                (TRUE));
 443                                if (ACPI_FAILURE(status)
 444                                    && ((status & AE_CODE_MASK) !=
 445                                        AE_CODE_CONTROL)) {
 446                                        if (status == AE_AML_NO_RETURN_VALUE) {
 447                                                ACPI_EXCEPTION((AE_INFO, status,
 448                                                                "Invoked method did not return a value"));
 449                                        }
 450
 451                                        ACPI_EXCEPTION((AE_INFO, status,
 452                                                        "GetPredicate Failed"));
 453                                        return_ACPI_STATUS(status);
 454                                }
 455
 456                                status =
 457                                    acpi_ps_next_parse_state(walk_state, op,
 458                                                             status);
 459                        }
 460
 461                        acpi_ps_pop_scope(parser_state, &op,
 462                                          &walk_state->arg_types,
 463                                          &walk_state->arg_count);
 464                        ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
 465                                          "Popped scope, Op=%p\n", op));
 466                } else if (walk_state->prev_op) {
 467
 468                        /* We were in the middle of an op */
 469
 470                        op = walk_state->prev_op;
 471                        walk_state->arg_types = walk_state->prev_arg_types;
 472                }
 473        }
 474#endif
 475
 476        /* Iterative parsing loop, while there is more AML to process: */
 477
 478        while ((parser_state->aml < parser_state->aml_end) || (op)) {
 479                aml_op_start = parser_state->aml;
 480                if (!op) {
 481                        status =
 482                            acpi_ps_create_op(walk_state, aml_op_start, &op);
 483                        if (ACPI_FAILURE(status)) {
 484                                if (status == AE_CTRL_PARSE_CONTINUE) {
 485                                        continue;
 486                                }
 487
 488                                if (status == AE_CTRL_PARSE_PENDING) {
 489                                        status = AE_OK;
 490                                }
 491
 492                                if (status == AE_CTRL_TERMINATE) {
 493                                        return_ACPI_STATUS(status);
 494                                }
 495
 496                                status =
 497                                    acpi_ps_complete_op(walk_state, &op,
 498                                                        status);
 499                                if (ACPI_FAILURE(status)) {
 500                                        return_ACPI_STATUS(status);
 501                                }
 502
 503                                continue;
 504                        }
 505
 506                        acpi_ex_start_trace_opcode(op, walk_state);
 507                }
 508
 509                /*
 510                 * Start arg_count at zero because we don't know if there are
 511                 * any args yet
 512                 */
 513                walk_state->arg_count = 0;
 514
 515                /* Are there any arguments that must be processed? */
 516
 517                if (walk_state->arg_types) {
 518
 519                        /* Get arguments */
 520
 521                        status =
 522                            acpi_ps_get_arguments(walk_state, aml_op_start, op);
 523                        if (ACPI_FAILURE(status)) {
 524                                status =
 525                                    acpi_ps_complete_op(walk_state, &op,
 526                                                        status);
 527                                if (ACPI_FAILURE(status)) {
 528                                        return_ACPI_STATUS(status);
 529                                }
 530
 531                                continue;
 532                        }
 533                }
 534
 535                /* Check for arguments that need to be processed */
 536
 537                if (walk_state->arg_count) {
 538                        /*
 539                         * There are arguments (complex ones), push Op and
 540                         * prepare for argument
 541                         */
 542                        status = acpi_ps_push_scope(parser_state, op,
 543                                                    walk_state->arg_types,
 544                                                    walk_state->arg_count);
 545                        if (ACPI_FAILURE(status)) {
 546                                status =
 547                                    acpi_ps_complete_op(walk_state, &op,
 548                                                        status);
 549                                if (ACPI_FAILURE(status)) {
 550                                        return_ACPI_STATUS(status);
 551                                }
 552
 553                                continue;
 554                        }
 555
 556                        op = NULL;
 557                        continue;
 558                }
 559
 560                /*
 561                 * All arguments have been processed -- Op is complete,
 562                 * prepare for next
 563                 */
 564                walk_state->op_info =
 565                    acpi_ps_get_opcode_info(op->common.aml_opcode);
 566                if (walk_state->op_info->flags & AML_NAMED) {
 567                        if (op->common.aml_opcode == AML_REGION_OP ||
 568                            op->common.aml_opcode == AML_DATA_REGION_OP) {
 569                                /*
 570                                 * Skip parsing of control method or opregion body,
 571                                 * because we don't have enough info in the first pass
 572                                 * to parse them correctly.
 573                                 *
 574                                 * Completed parsing an op_region declaration, we now
 575                                 * know the length.
 576                                 */
 577                                op->named.length =
 578                                    (u32) (parser_state->aml - op->named.data);
 579                        }
 580                }
 581
 582                if (walk_state->op_info->flags & AML_CREATE) {
 583                        /*
 584                         * Backup to beginning of create_XXXfield declaration (1 for
 585                         * Opcode)
 586                         *
 587                         * body_length is unknown until we parse the body
 588                         */
 589                        op->named.length =
 590                            (u32) (parser_state->aml - op->named.data);
 591                }
 592
 593                if (op->common.aml_opcode == AML_BANK_FIELD_OP) {
 594                        /*
 595                         * Backup to beginning of bank_field declaration
 596                         *
 597                         * body_length is unknown until we parse the body
 598                         */
 599                        op->named.length =
 600                            (u32) (parser_state->aml - op->named.data);
 601                }
 602
 603                /* This op complete, notify the dispatcher */
 604
 605                if (walk_state->ascending_callback != NULL) {
 606                        walk_state->op = op;
 607                        walk_state->opcode = op->common.aml_opcode;
 608
 609                        status = walk_state->ascending_callback(walk_state);
 610                        status =
 611                            acpi_ps_next_parse_state(walk_state, op, status);
 612                        if (status == AE_CTRL_PENDING) {
 613                                status = AE_OK;
 614                        }
 615                }
 616
 617                status = acpi_ps_complete_op(walk_state, &op, status);
 618                if (ACPI_FAILURE(status)) {
 619                        return_ACPI_STATUS(status);
 620                }
 621
 622        }                       /* while parser_state->Aml */
 623
 624        status = acpi_ps_complete_final_op(walk_state, op, status);
 625        return_ACPI_STATUS(status);
 626}
 627