linux/drivers/acpi/acpica/psloop.c
<<
>>
Prefs
   1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2/******************************************************************************
   3 *
   4 * Module Name: psloop - Main AML parse loop
   5 *
   6 * Copyright (C) 2000 - 2021, Intel Corp.
   7 *
   8 *****************************************************************************/
   9
  10/*
  11 * Parse the AML and build an operation tree as most interpreters, (such as
  12 * Perl) do. Parsing is done by hand rather than with a YACC generated parser
  13 * to tightly constrain stack and dynamic memory usage. Parsing is kept
  14 * flexible and the code fairly compact by parsing based on a list of AML
  15 * opcode templates in aml_op_info[].
  16 */
  17
  18#include <acpi/acpi.h>
  19#include "accommon.h"
  20#include "acinterp.h"
  21#include "acparser.h"
  22#include "acdispat.h"
  23#include "amlcode.h"
  24#include "acconvert.h"
  25#include "acnamesp.h"
  26
  27#define _COMPONENT          ACPI_PARSER
  28ACPI_MODULE_NAME("psloop")
  29
  30/* Local prototypes */
  31static acpi_status
  32acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
  33                      u8 * aml_op_start, union acpi_parse_object *op);
  34
  35/*******************************************************************************
  36 *
  37 * FUNCTION:    acpi_ps_get_arguments
  38 *
  39 * PARAMETERS:  walk_state          - Current state
  40 *              aml_op_start        - Op start in AML
  41 *              op                  - Current Op
  42 *
  43 * RETURN:      Status
  44 *
  45 * DESCRIPTION: Get arguments for passed Op.
  46 *
  47 ******************************************************************************/
  48
  49static acpi_status
  50acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
  51                      u8 * aml_op_start, union acpi_parse_object *op)
  52{
  53        acpi_status status = AE_OK;
  54        union acpi_parse_object *arg = NULL;
  55
  56        ACPI_FUNCTION_TRACE_PTR(ps_get_arguments, walk_state);
  57
  58        ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
  59                          "Get arguments for opcode [%s]\n",
  60                          op->common.aml_op_name));
  61
  62        switch (op->common.aml_opcode) {
  63        case AML_BYTE_OP:       /* AML_BYTEDATA_ARG */
  64        case AML_WORD_OP:       /* AML_WORDDATA_ARG */
  65        case AML_DWORD_OP:      /* AML_DWORDATA_ARG */
  66        case AML_QWORD_OP:      /* AML_QWORDATA_ARG */
  67        case AML_STRING_OP:     /* AML_ASCIICHARLIST_ARG */
  68
  69                /* Fill in constant or string argument directly */
  70
  71                acpi_ps_get_next_simple_arg(&(walk_state->parser_state),
  72                                            GET_CURRENT_ARG_TYPE(walk_state->
  73                                                                 arg_types),
  74                                            op);
  75                break;
  76
  77        case AML_INT_NAMEPATH_OP:       /* AML_NAMESTRING_ARG */
  78
  79                status = acpi_ps_get_next_namepath(walk_state,
  80                                                   &(walk_state->parser_state),
  81                                                   op,
  82                                                   ACPI_POSSIBLE_METHOD_CALL);
  83                if (ACPI_FAILURE(status)) {
  84                        return_ACPI_STATUS(status);
  85                }
  86
  87                walk_state->arg_types = 0;
  88                break;
  89
  90        default:
  91                /*
  92                 * Op is not a constant or string, append each argument to the Op
  93                 */
  94                while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) &&
  95                       !walk_state->arg_count) {
  96                        walk_state->aml = walk_state->parser_state.aml;
  97
  98                        switch (op->common.aml_opcode) {
  99                        case AML_METHOD_OP:
 100                        case AML_BUFFER_OP:
 101                        case AML_PACKAGE_OP:
 102                        case AML_VARIABLE_PACKAGE_OP:
 103                        case AML_WHILE_OP:
 104
 105                                break;
 106
 107                        default:
 108
 109                                ASL_CV_CAPTURE_COMMENTS(walk_state);
 110                                break;
 111                        }
 112
 113                        status =
 114                            acpi_ps_get_next_arg(walk_state,
 115                                                 &(walk_state->parser_state),
 116                                                 GET_CURRENT_ARG_TYPE
 117                                                 (walk_state->arg_types), &arg);
 118                        if (ACPI_FAILURE(status)) {
 119                                return_ACPI_STATUS(status);
 120                        }
 121
 122                        if (arg) {
 123                                acpi_ps_append_arg(op, arg);
 124                        }
 125
 126                        INCREMENT_ARG_LIST(walk_state->arg_types);
 127                }
 128
 129                ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
 130                                  "Final argument count: %8.8X pass %u\n",
 131                                  walk_state->arg_count,
 132                                  walk_state->pass_number));
 133
 134                /* Special processing for certain opcodes */
 135
 136                switch (op->common.aml_opcode) {
 137                case AML_METHOD_OP:
 138                        /*
 139                         * Skip parsing of control method because we don't have enough
 140                         * info in the first pass to parse it correctly.
 141                         *
 142                         * Save the length and address of the body
 143                         */
 144                        op->named.data = walk_state->parser_state.aml;
 145                        op->named.length = (u32)
 146                            (walk_state->parser_state.pkg_end -
 147                             walk_state->parser_state.aml);
 148
 149                        /* Skip body of method */
 150
 151                        walk_state->parser_state.aml =
 152                            walk_state->parser_state.pkg_end;
 153                        walk_state->arg_count = 0;
 154                        break;
 155
 156                case AML_BUFFER_OP:
 157                case AML_PACKAGE_OP:
 158                case AML_VARIABLE_PACKAGE_OP:
 159
 160                        if ((op->common.parent) &&
 161                            (op->common.parent->common.aml_opcode ==
 162                             AML_NAME_OP)
 163                            && (walk_state->pass_number <=
 164                                ACPI_IMODE_LOAD_PASS2)) {
 165                                ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
 166                                                  "Setup Package/Buffer: Pass %u, AML Ptr: %p\n",
 167                                                  walk_state->pass_number,
 168                                                  aml_op_start));
 169
 170                                /*
 171                                 * Skip parsing of Buffers and Packages because we don't have
 172                                 * enough info in the first pass to parse them correctly.
 173                                 */
 174                                op->named.data = aml_op_start;
 175                                op->named.length = (u32)
 176                                    (walk_state->parser_state.pkg_end -
 177                                     aml_op_start);
 178
 179                                /* Skip body */
 180
 181                                walk_state->parser_state.aml =
 182                                    walk_state->parser_state.pkg_end;
 183                                walk_state->arg_count = 0;
 184                        }
 185                        break;
 186
 187                case AML_WHILE_OP:
 188
 189                        if (walk_state->control_state) {
 190                                walk_state->control_state->control.package_end =
 191                                    walk_state->parser_state.pkg_end;
 192                        }
 193                        break;
 194
 195                default:
 196
 197                        /* No action for all other opcodes */
 198
 199                        break;
 200                }
 201
 202                break;
 203        }
 204
 205        return_ACPI_STATUS(AE_OK);
 206}
 207
 208/*******************************************************************************
 209 *
 210 * FUNCTION:    acpi_ps_parse_loop
 211 *
 212 * PARAMETERS:  walk_state          - Current state
 213 *
 214 * RETURN:      Status
 215 *
 216 * DESCRIPTION: Parse AML (pointed to by the current parser state) and return
 217 *              a tree of ops.
 218 *
 219 ******************************************************************************/
 220
 221acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
 222{
 223        acpi_status status = AE_OK;
 224        union acpi_parse_object *op = NULL;     /* current op */
 225        struct acpi_parse_state *parser_state;
 226        u8 *aml_op_start = NULL;
 227        u8 opcode_length;
 228
 229        ACPI_FUNCTION_TRACE_PTR(ps_parse_loop, walk_state);
 230
 231        if (walk_state->descending_callback == NULL) {
 232                return_ACPI_STATUS(AE_BAD_PARAMETER);
 233        }
 234
 235        parser_state = &walk_state->parser_state;
 236        walk_state->arg_types = 0;
 237
 238#ifndef ACPI_CONSTANT_EVAL_ONLY
 239
 240        if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) {
 241
 242                /* We are restarting a preempted control method */
 243
 244                if (acpi_ps_has_completed_scope(parser_state)) {
 245                        /*
 246                         * We must check if a predicate to an IF or WHILE statement
 247                         * was just completed
 248                         */
 249                        if ((parser_state->scope->parse_scope.op) &&
 250                            ((parser_state->scope->parse_scope.op->common.
 251                              aml_opcode == AML_IF_OP)
 252                             || (parser_state->scope->parse_scope.op->common.
 253                                 aml_opcode == AML_WHILE_OP))
 254                            && (walk_state->control_state)
 255                            && (walk_state->control_state->common.state ==
 256                                ACPI_CONTROL_PREDICATE_EXECUTING)) {
 257                                /*
 258                                 * A predicate was just completed, get the value of the
 259                                 * predicate and branch based on that value
 260                                 */
 261                                walk_state->op = NULL;
 262                                status =
 263                                    acpi_ds_get_predicate_value(walk_state,
 264                                                                ACPI_TO_POINTER
 265                                                                (TRUE));
 266                                if (ACPI_FAILURE(status)
 267                                    && !ACPI_CNTL_EXCEPTION(status)) {
 268                                        if (status == AE_AML_NO_RETURN_VALUE) {
 269                                                ACPI_EXCEPTION((AE_INFO, status,
 270                                                                "Invoked method did not return a value"));
 271                                        }
 272
 273                                        ACPI_EXCEPTION((AE_INFO, status,
 274                                                        "GetPredicate Failed"));
 275                                        return_ACPI_STATUS(status);
 276                                }
 277
 278                                status =
 279                                    acpi_ps_next_parse_state(walk_state, op,
 280                                                             status);
 281                        }
 282
 283                        acpi_ps_pop_scope(parser_state, &op,
 284                                          &walk_state->arg_types,
 285                                          &walk_state->arg_count);
 286                        ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
 287                                          "Popped scope, Op=%p\n", op));
 288                } else if (walk_state->prev_op) {
 289
 290                        /* We were in the middle of an op */
 291
 292                        op = walk_state->prev_op;
 293                        walk_state->arg_types = walk_state->prev_arg_types;
 294                }
 295        }
 296#endif
 297
 298        /* Iterative parsing loop, while there is more AML to process: */
 299
 300        while ((parser_state->aml < parser_state->aml_end) || (op)) {
 301                ASL_CV_CAPTURE_COMMENTS(walk_state);
 302
 303                aml_op_start = parser_state->aml;
 304                if (!op) {
 305                        status =
 306                            acpi_ps_create_op(walk_state, aml_op_start, &op);
 307                        if (ACPI_FAILURE(status)) {
 308                                /*
 309                                 * ACPI_PARSE_MODULE_LEVEL means that we are loading a table by
 310                                 * executing it as a control method. However, if we encounter
 311                                 * an error while loading the table, we need to keep trying to
 312                                 * load the table rather than aborting the table load. Set the
 313                                 * status to AE_OK to proceed with the table load.
 314                                 */
 315                                if ((walk_state->
 316                                     parse_flags & ACPI_PARSE_MODULE_LEVEL)
 317                                    && ((status == AE_ALREADY_EXISTS)
 318                                        || (status == AE_NOT_FOUND))) {
 319                                        status = AE_OK;
 320                                }
 321                                if (status == AE_CTRL_PARSE_CONTINUE) {
 322                                        continue;
 323                                }
 324
 325                                if (status == AE_CTRL_PARSE_PENDING) {
 326                                        status = AE_OK;
 327                                }
 328
 329                                if (status == AE_CTRL_TERMINATE) {
 330                                        return_ACPI_STATUS(status);
 331                                }
 332
 333                                status =
 334                                    acpi_ps_complete_op(walk_state, &op,
 335                                                        status);
 336                                if (ACPI_FAILURE(status)) {
 337                                        return_ACPI_STATUS(status);
 338                                }
 339                                if (acpi_ns_opens_scope
 340                                    (acpi_ps_get_opcode_info
 341                                     (walk_state->opcode)->object_type)) {
 342                                        /*
 343                                         * If the scope/device op fails to parse, skip the body of
 344                                         * the scope op because the parse failure indicates that
 345                                         * the device may not exist.
 346                                         */
 347                                        ACPI_INFO(("Skipping parse of AML opcode: %s (0x%4.4X)", acpi_ps_get_opcode_name(walk_state->opcode), walk_state->opcode));
 348
 349                                        /*
 350                                         * Determine the opcode length before skipping the opcode.
 351                                         * An opcode can be 1 byte or 2 bytes in length.
 352                                         */
 353                                        opcode_length = 1;
 354                                        if ((walk_state->opcode & 0xFF00) ==
 355                                            AML_EXTENDED_OPCODE) {
 356                                                opcode_length = 2;
 357                                        }
 358                                        walk_state->parser_state.aml =
 359                                            walk_state->aml + opcode_length;
 360
 361                                        walk_state->parser_state.aml =
 362                                            acpi_ps_get_next_package_end
 363                                            (&walk_state->parser_state);
 364                                        walk_state->aml =
 365                                            walk_state->parser_state.aml;
 366                                }
 367
 368                                continue;
 369                        }
 370
 371                        acpi_ex_start_trace_opcode(op, walk_state);
 372                }
 373
 374                /*
 375                 * Start arg_count at zero because we don't know if there are
 376                 * any args yet
 377                 */
 378                walk_state->arg_count = 0;
 379
 380                switch (op->common.aml_opcode) {
 381                case AML_BYTE_OP:
 382                case AML_WORD_OP:
 383                case AML_DWORD_OP:
 384                case AML_QWORD_OP:
 385
 386                        break;
 387
 388                default:
 389
 390                        ASL_CV_CAPTURE_COMMENTS(walk_state);
 391                        break;
 392                }
 393
 394                /* Are there any arguments that must be processed? */
 395
 396                if (walk_state->arg_types) {
 397
 398                        /* Get arguments */
 399
 400                        status =
 401                            acpi_ps_get_arguments(walk_state, aml_op_start, op);
 402                        if (ACPI_FAILURE(status)) {
 403                                status =
 404                                    acpi_ps_complete_op(walk_state, &op,
 405                                                        status);
 406                                if (ACPI_FAILURE(status)) {
 407                                        return_ACPI_STATUS(status);
 408                                }
 409                                if ((walk_state->control_state) &&
 410                                    ((walk_state->control_state->control.
 411                                      opcode == AML_IF_OP)
 412                                     || (walk_state->control_state->control.
 413                                         opcode == AML_WHILE_OP))) {
 414                                        /*
 415                                         * If the if/while op fails to parse, we will skip parsing
 416                                         * the body of the op.
 417                                         */
 418                                        parser_state->aml =
 419                                            walk_state->control_state->control.
 420                                            aml_predicate_start + 1;
 421                                        parser_state->aml =
 422                                            acpi_ps_get_next_package_end
 423                                            (parser_state);
 424                                        walk_state->aml = parser_state->aml;
 425
 426                                        ACPI_ERROR((AE_INFO,
 427                                                    "Skipping While/If block"));
 428                                        if (*walk_state->aml == AML_ELSE_OP) {
 429                                                ACPI_ERROR((AE_INFO,
 430                                                            "Skipping Else block"));
 431                                                walk_state->parser_state.aml =
 432                                                    walk_state->aml + 1;
 433                                                walk_state->parser_state.aml =
 434                                                    acpi_ps_get_next_package_end
 435                                                    (parser_state);
 436                                                walk_state->aml =
 437                                                    parser_state->aml;
 438                                        }
 439                                        ACPI_FREE(acpi_ut_pop_generic_state
 440                                                  (&walk_state->control_state));
 441                                }
 442                                op = NULL;
 443                                continue;
 444                        }
 445                }
 446
 447                /* Check for arguments that need to be processed */
 448
 449                ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
 450                                  "Parseloop: argument count: %8.8X\n",
 451                                  walk_state->arg_count));
 452
 453                if (walk_state->arg_count) {
 454                        /*
 455                         * There are arguments (complex ones), push Op and
 456                         * prepare for argument
 457                         */
 458                        status = acpi_ps_push_scope(parser_state, op,
 459                                                    walk_state->arg_types,
 460                                                    walk_state->arg_count);
 461                        if (ACPI_FAILURE(status)) {
 462                                status =
 463                                    acpi_ps_complete_op(walk_state, &op,
 464                                                        status);
 465                                if (ACPI_FAILURE(status)) {
 466                                        return_ACPI_STATUS(status);
 467                                }
 468
 469                                continue;
 470                        }
 471
 472                        op = NULL;
 473                        continue;
 474                }
 475
 476                /*
 477                 * All arguments have been processed -- Op is complete,
 478                 * prepare for next
 479                 */
 480                walk_state->op_info =
 481                    acpi_ps_get_opcode_info(op->common.aml_opcode);
 482                if (walk_state->op_info->flags & AML_NAMED) {
 483                        if (op->common.aml_opcode == AML_REGION_OP ||
 484                            op->common.aml_opcode == AML_DATA_REGION_OP) {
 485                                /*
 486                                 * Skip parsing of control method or opregion body,
 487                                 * because we don't have enough info in the first pass
 488                                 * to parse them correctly.
 489                                 *
 490                                 * Completed parsing an op_region declaration, we now
 491                                 * know the length.
 492                                 */
 493                                op->named.length =
 494                                    (u32) (parser_state->aml - op->named.data);
 495                        }
 496                }
 497
 498                if (walk_state->op_info->flags & AML_CREATE) {
 499                        /*
 500                         * Backup to beginning of create_XXXfield declaration (1 for
 501                         * Opcode)
 502                         *
 503                         * body_length is unknown until we parse the body
 504                         */
 505                        op->named.length =
 506                            (u32) (parser_state->aml - op->named.data);
 507                }
 508
 509                if (op->common.aml_opcode == AML_BANK_FIELD_OP) {
 510                        /*
 511                         * Backup to beginning of bank_field declaration
 512                         *
 513                         * body_length is unknown until we parse the body
 514                         */
 515                        op->named.length =
 516                            (u32) (parser_state->aml - op->named.data);
 517                }
 518
 519                /* This op complete, notify the dispatcher */
 520
 521                if (walk_state->ascending_callback != NULL) {
 522                        walk_state->op = op;
 523                        walk_state->opcode = op->common.aml_opcode;
 524
 525                        status = walk_state->ascending_callback(walk_state);
 526                        status =
 527                            acpi_ps_next_parse_state(walk_state, op, status);
 528                        if (status == AE_CTRL_PENDING) {
 529                                status = AE_OK;
 530                        } else
 531                            if ((walk_state->
 532                                 parse_flags & ACPI_PARSE_MODULE_LEVEL)
 533                                && (ACPI_AML_EXCEPTION(status)
 534                                    || status == AE_ALREADY_EXISTS
 535                                    || status == AE_NOT_FOUND)) {
 536                                /*
 537                                 * ACPI_PARSE_MODULE_LEVEL flag means that we
 538                                 * are currently loading a table by executing
 539                                 * it as a control method. However, if we
 540                                 * encounter an error while loading the table,
 541                                 * we need to keep trying to load the table
 542                                 * rather than aborting the table load (setting
 543                                 * the status to AE_OK continues the table
 544                                 * load). If we get a failure at this point, it
 545                                 * means that the dispatcher got an error while
 546                                 * trying to execute the Op.
 547                                 */
 548                                status = AE_OK;
 549                        }
 550                }
 551
 552                status = acpi_ps_complete_op(walk_state, &op, status);
 553                if (ACPI_FAILURE(status)) {
 554                        return_ACPI_STATUS(status);
 555                }
 556
 557        }                       /* while parser_state->Aml */
 558
 559        status = acpi_ps_complete_final_op(walk_state, op, status);
 560        return_ACPI_STATUS(status);
 561}
 562