root/drivers/acpi/acpica/psloop.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ACPI_MODULE_NAME
  2. acpi_ps_parse_loop

   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 - 2019, 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
  28 ACPI_MODULE_NAME("psloop")
  29 
  30 /* Local prototypes */
  31 static acpi_status
  32 acpi_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 
  49 static acpi_status
  50 acpi_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 
 221 acpi_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                                     && ((status & AE_CODE_MASK) !=
 268                                         AE_CODE_CONTROL)) {
 269                                         if (status == AE_AML_NO_RETURN_VALUE) {
 270                                                 ACPI_EXCEPTION((AE_INFO, status,
 271                                                                 "Invoked method did not return a value"));
 272                                         }
 273 
 274                                         ACPI_EXCEPTION((AE_INFO, status,
 275                                                         "GetPredicate Failed"));
 276                                         return_ACPI_STATUS(status);
 277                                 }
 278 
 279                                 status =
 280                                     acpi_ps_next_parse_state(walk_state, op,
 281                                                              status);
 282                         }
 283 
 284                         acpi_ps_pop_scope(parser_state, &op,
 285                                           &walk_state->arg_types,
 286                                           &walk_state->arg_count);
 287                         ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
 288                                           "Popped scope, Op=%p\n", op));
 289                 } else if (walk_state->prev_op) {
 290 
 291                         /* We were in the middle of an op */
 292 
 293                         op = walk_state->prev_op;
 294                         walk_state->arg_types = walk_state->prev_arg_types;
 295                 }
 296         }
 297 #endif
 298 
 299         /* Iterative parsing loop, while there is more AML to process: */
 300 
 301         while ((parser_state->aml < parser_state->aml_end) || (op)) {
 302                 ASL_CV_CAPTURE_COMMENTS(walk_state);
 303 
 304                 aml_op_start = parser_state->aml;
 305                 if (!op) {
 306                         status =
 307                             acpi_ps_create_op(walk_state, aml_op_start, &op);
 308                         if (ACPI_FAILURE(status)) {
 309                                 /*
 310                                  * ACPI_PARSE_MODULE_LEVEL means that we are loading a table by
 311                                  * executing it as a control method. However, if we encounter
 312                                  * an error while loading the table, we need to keep trying to
 313                                  * load the table rather than aborting the table load. Set the
 314                                  * status to AE_OK to proceed with the table load.
 315                                  */
 316                                 if ((walk_state->
 317                                      parse_flags & ACPI_PARSE_MODULE_LEVEL)
 318                                     && ((status == AE_ALREADY_EXISTS)
 319                                         || (status == AE_NOT_FOUND))) {
 320                                         status = AE_OK;
 321                                 }
 322                                 if (status == AE_CTRL_PARSE_CONTINUE) {
 323                                         continue;
 324                                 }
 325 
 326                                 if (status == AE_CTRL_PARSE_PENDING) {
 327                                         status = AE_OK;
 328                                 }
 329 
 330                                 if (status == AE_CTRL_TERMINATE) {
 331                                         return_ACPI_STATUS(status);
 332                                 }
 333 
 334                                 status =
 335                                     acpi_ps_complete_op(walk_state, &op,
 336                                                         status);
 337                                 if (ACPI_FAILURE(status)) {
 338                                         return_ACPI_STATUS(status);
 339                                 }
 340                                 if (acpi_ns_opens_scope
 341                                     (acpi_ps_get_opcode_info
 342                                      (walk_state->opcode)->object_type)) {
 343                                         /*
 344                                          * If the scope/device op fails to parse, skip the body of
 345                                          * the scope op because the parse failure indicates that
 346                                          * the device may not exist.
 347                                          */
 348                                         ACPI_INFO(("Skipping parse of AML opcode: %s (0x%4.4X)", acpi_ps_get_opcode_name(walk_state->opcode), walk_state->opcode));
 349 
 350                                         /*
 351                                          * Determine the opcode length before skipping the opcode.
 352                                          * An opcode can be 1 byte or 2 bytes in length.
 353                                          */
 354                                         opcode_length = 1;
 355                                         if ((walk_state->opcode & 0xFF00) ==
 356                                             AML_EXTENDED_OPCODE) {
 357                                                 opcode_length = 2;
 358                                         }
 359                                         walk_state->parser_state.aml =
 360                                             walk_state->aml + opcode_length;
 361 
 362                                         walk_state->parser_state.aml =
 363                                             acpi_ps_get_next_package_end
 364                                             (&walk_state->parser_state);
 365                                         walk_state->aml =
 366                                             walk_state->parser_state.aml;
 367                                 }
 368 
 369                                 continue;
 370                         }
 371 
 372                         acpi_ex_start_trace_opcode(op, walk_state);
 373                 }
 374 
 375                 /*
 376                  * Start arg_count at zero because we don't know if there are
 377                  * any args yet
 378                  */
 379                 walk_state->arg_count = 0;
 380 
 381                 switch (op->common.aml_opcode) {
 382                 case AML_BYTE_OP:
 383                 case AML_WORD_OP:
 384                 case AML_DWORD_OP:
 385                 case AML_QWORD_OP:
 386 
 387                         break;
 388 
 389                 default:
 390 
 391                         ASL_CV_CAPTURE_COMMENTS(walk_state);
 392                         break;
 393                 }
 394 
 395                 /* Are there any arguments that must be processed? */
 396 
 397                 if (walk_state->arg_types) {
 398 
 399                         /* Get arguments */
 400 
 401                         status =
 402                             acpi_ps_get_arguments(walk_state, aml_op_start, op);
 403                         if (ACPI_FAILURE(status)) {
 404                                 status =
 405                                     acpi_ps_complete_op(walk_state, &op,
 406                                                         status);
 407                                 if (ACPI_FAILURE(status)) {
 408                                         return_ACPI_STATUS(status);
 409                                 }
 410                                 if ((walk_state->control_state) &&
 411                                     ((walk_state->control_state->control.
 412                                       opcode == AML_IF_OP)
 413                                      || (walk_state->control_state->control.
 414                                          opcode == AML_WHILE_OP))) {
 415                                         /*
 416                                          * If the if/while op fails to parse, we will skip parsing
 417                                          * the body of the op.
 418                                          */
 419                                         parser_state->aml =
 420                                             walk_state->control_state->control.
 421                                             aml_predicate_start + 1;
 422                                         parser_state->aml =
 423                                             acpi_ps_get_next_package_end
 424                                             (parser_state);
 425                                         walk_state->aml = parser_state->aml;
 426 
 427                                         ACPI_ERROR((AE_INFO,
 428                                                     "Skipping While/If block"));
 429                                         if (*walk_state->aml == AML_ELSE_OP) {
 430                                                 ACPI_ERROR((AE_INFO,
 431                                                             "Skipping Else block"));
 432                                                 walk_state->parser_state.aml =
 433                                                     walk_state->aml + 1;
 434                                                 walk_state->parser_state.aml =
 435                                                     acpi_ps_get_next_package_end
 436                                                     (parser_state);
 437                                                 walk_state->aml =
 438                                                     parser_state->aml;
 439                                         }
 440                                         ACPI_FREE(acpi_ut_pop_generic_state
 441                                                   (&walk_state->control_state));
 442                                 }
 443                                 op = NULL;
 444                                 continue;
 445                         }
 446                 }
 447 
 448                 /* Check for arguments that need to be processed */
 449 
 450                 ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
 451                                   "Parseloop: argument count: %8.8X\n",
 452                                   walk_state->arg_count));
 453 
 454                 if (walk_state->arg_count) {
 455                         /*
 456                          * There are arguments (complex ones), push Op and
 457                          * prepare for argument
 458                          */
 459                         status = acpi_ps_push_scope(parser_state, op,
 460                                                     walk_state->arg_types,
 461                                                     walk_state->arg_count);
 462                         if (ACPI_FAILURE(status)) {
 463                                 status =
 464                                     acpi_ps_complete_op(walk_state, &op,
 465                                                         status);
 466                                 if (ACPI_FAILURE(status)) {
 467                                         return_ACPI_STATUS(status);
 468                                 }
 469 
 470                                 continue;
 471                         }
 472 
 473                         op = NULL;
 474                         continue;
 475                 }
 476 
 477                 /*
 478                  * All arguments have been processed -- Op is complete,
 479                  * prepare for next
 480                  */
 481                 walk_state->op_info =
 482                     acpi_ps_get_opcode_info(op->common.aml_opcode);
 483                 if (walk_state->op_info->flags & AML_NAMED) {
 484                         if (op->common.aml_opcode == AML_REGION_OP ||
 485                             op->common.aml_opcode == AML_DATA_REGION_OP) {
 486                                 /*
 487                                  * Skip parsing of control method or opregion body,
 488                                  * because we don't have enough info in the first pass
 489                                  * to parse them correctly.
 490                                  *
 491                                  * Completed parsing an op_region declaration, we now
 492                                  * know the length.
 493                                  */
 494                                 op->named.length =
 495                                     (u32) (parser_state->aml - op->named.data);
 496                         }
 497                 }
 498 
 499                 if (walk_state->op_info->flags & AML_CREATE) {
 500                         /*
 501                          * Backup to beginning of create_XXXfield declaration (1 for
 502                          * Opcode)
 503                          *
 504                          * body_length is unknown until we parse the body
 505                          */
 506                         op->named.length =
 507                             (u32) (parser_state->aml - op->named.data);
 508                 }
 509 
 510                 if (op->common.aml_opcode == AML_BANK_FIELD_OP) {
 511                         /*
 512                          * Backup to beginning of bank_field declaration
 513                          *
 514                          * body_length is unknown until we parse the body
 515                          */
 516                         op->named.length =
 517                             (u32) (parser_state->aml - op->named.data);
 518                 }
 519 
 520                 /* This op complete, notify the dispatcher */
 521 
 522                 if (walk_state->ascending_callback != NULL) {
 523                         walk_state->op = op;
 524                         walk_state->opcode = op->common.aml_opcode;
 525 
 526                         status = walk_state->ascending_callback(walk_state);
 527                         status =
 528                             acpi_ps_next_parse_state(walk_state, op, status);
 529                         if (status == AE_CTRL_PENDING) {
 530                                 status = AE_OK;
 531                         } else
 532                             if ((walk_state->
 533                                  parse_flags & ACPI_PARSE_MODULE_LEVEL)
 534                                 && (ACPI_AML_EXCEPTION(status)
 535                                     || status == AE_ALREADY_EXISTS
 536                                     || status == AE_NOT_FOUND)) {
 537                                 /*
 538                                  * ACPI_PARSE_MODULE_LEVEL flag means that we
 539                                  * are currently loading a table by executing
 540                                  * it as a control method. However, if we
 541                                  * encounter an error while loading the table,
 542                                  * we need to keep trying to load the table
 543                                  * rather than aborting the table load (setting
 544                                  * the status to AE_OK continues the table
 545                                  * load). If we get a failure at this point, it
 546                                  * means that the dispatcher got an error while
 547                                  * trying to execute the Op.
 548                                  */
 549                                 status = AE_OK;
 550                         }
 551                 }
 552 
 553                 status = acpi_ps_complete_op(walk_state, &op, status);
 554                 if (ACPI_FAILURE(status)) {
 555                         return_ACPI_STATUS(status);
 556                 }
 557 
 558         }                       /* while parser_state->Aml */
 559 
 560         status = acpi_ps_complete_final_op(walk_state, op, status);
 561         return_ACPI_STATUS(status);
 562 }

/* [<][>][^][v][top][bottom][index][help] */