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