1 /****************************************************************************** 2 * 3 * Module Name: psobject - Support for parse objects 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2013, 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 #include <contrib/dev/acpica/include/acpi.h> 46 #include <contrib/dev/acpica/include/accommon.h> 47 #include <contrib/dev/acpica/include/acparser.h> 48 #include <contrib/dev/acpica/include/amlcode.h> 49 50 #define _COMPONENT ACPI_PARSER 51 ACPI_MODULE_NAME ("psobject") 52 53 54 /* Local prototypes */ 55 56 static ACPI_STATUS 57 AcpiPsGetAmlOpcode ( 58 ACPI_WALK_STATE *WalkState); 59 60 61 /******************************************************************************* 62 * 63 * FUNCTION: AcpiPsGetAmlOpcode 64 * 65 * PARAMETERS: WalkState - Current state 66 * 67 * RETURN: Status 68 * 69 * DESCRIPTION: Extract the next AML opcode from the input stream. 70 * 71 ******************************************************************************/ 72 73 static ACPI_STATUS 74 AcpiPsGetAmlOpcode ( 75 ACPI_WALK_STATE *WalkState) 76 { 77 78 ACPI_FUNCTION_TRACE_PTR (PsGetAmlOpcode, WalkState); 79 80 81 WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->ParserState.Aml, 82 WalkState->ParserState.AmlStart); 83 WalkState->Opcode = AcpiPsPeekOpcode (&(WalkState->ParserState)); 84 85 /* 86 * First cut to determine what we have found: 87 * 1) A valid AML opcode 88 * 2) A name string 89 * 3) An unknown/invalid opcode 90 */ 91 WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode); 92 93 switch (WalkState->OpInfo->Class) 94 { 95 case AML_CLASS_ASCII: 96 case AML_CLASS_PREFIX: 97 /* 98 * Starts with a valid prefix or ASCII char, this is a name 99 * string. Convert the bare name string to a namepath. 100 */ 101 WalkState->Opcode = AML_INT_NAMEPATH_OP; 102 WalkState->ArgTypes = ARGP_NAMESTRING; 103 break; 104 105 case AML_CLASS_UNKNOWN: 106 107 /* The opcode is unrecognized. Complain and skip unknown opcodes */ 108 109 if (WalkState->PassNumber == 2) 110 { 111 ACPI_ERROR ((AE_INFO, 112 "Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring", 113 WalkState->Opcode, 114 (UINT32) (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER)))); 115 116 ACPI_DUMP_BUFFER ((WalkState->ParserState.Aml - 16), 48); 117 118 #ifdef ACPI_ASL_COMPILER 119 /* 120 * This is executed for the disassembler only. Output goes 121 * to the disassembled ASL output file. 122 */ 123 AcpiOsPrintf ( 124 "/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n", 125 WalkState->Opcode, 126 (UINT32) (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER))); 127 128 /* Dump the context surrounding the invalid opcode */ 129 130 AcpiUtDumpBuffer (((UINT8 *) WalkState->ParserState.Aml - 16), 131 48, DB_BYTE_DISPLAY, 132 (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER) - 16)); 133 AcpiOsPrintf (" */\n"); 134 #endif 135 } 136 137 /* Increment past one-byte or two-byte opcode */ 138 139 WalkState->ParserState.Aml++; 140 if (WalkState->Opcode > 0xFF) /* Can only happen if first byte is 0x5B */ 141 { 142 WalkState->ParserState.Aml++; 143 } 144 145 return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE); 146 147 default: 148 149 /* Found opcode info, this is a normal opcode */ 150 151 WalkState->ParserState.Aml += AcpiPsGetOpcodeSize (WalkState->Opcode); 152 WalkState->ArgTypes = WalkState->OpInfo->ParseArgs; 153 break; 154 } 155 156 return_ACPI_STATUS (AE_OK); 157 } 158 159 160 /******************************************************************************* 161 * 162 * FUNCTION: AcpiPsBuildNamedOp 163 * 164 * PARAMETERS: WalkState - Current state 165 * AmlOpStart - Begin of named Op in AML 166 * UnnamedOp - Early Op (not a named Op) 167 * Op - Returned Op 168 * 169 * RETURN: Status 170 * 171 * DESCRIPTION: Parse a named Op 172 * 173 ******************************************************************************/ 174 175 ACPI_STATUS 176 AcpiPsBuildNamedOp ( 177 ACPI_WALK_STATE *WalkState, 178 UINT8 *AmlOpStart, 179 ACPI_PARSE_OBJECT *UnnamedOp, 180 ACPI_PARSE_OBJECT **Op) 181 { 182 ACPI_STATUS Status = AE_OK; 183 ACPI_PARSE_OBJECT *Arg = NULL; 184 185 186 ACPI_FUNCTION_TRACE_PTR (PsBuildNamedOp, WalkState); 187 188 189 UnnamedOp->Common.Value.Arg = NULL; 190 UnnamedOp->Common.ArgListLength = 0; 191 UnnamedOp->Common.AmlOpcode = WalkState->Opcode; 192 193 /* 194 * Get and append arguments until we find the node that contains 195 * the name (the type ARGP_NAME). 196 */ 197 while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) && 198 (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) != ARGP_NAME)) 199 { 200 Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState), 201 GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg); 202 if (ACPI_FAILURE (Status)) 203 { 204 return_ACPI_STATUS (Status); 205 } 206 207 AcpiPsAppendArg (UnnamedOp, Arg); 208 INCREMENT_ARG_LIST (WalkState->ArgTypes); 209 } 210 211 /* 212 * Make sure that we found a NAME and didn't run out of arguments 213 */ 214 if (!GET_CURRENT_ARG_TYPE (WalkState->ArgTypes)) 215 { 216 return_ACPI_STATUS (AE_AML_NO_OPERAND); 217 } 218 219 /* We know that this arg is a name, move to next arg */ 220 221 INCREMENT_ARG_LIST (WalkState->ArgTypes); 222 223 /* 224 * Find the object. This will either insert the object into 225 * the namespace or simply look it up 226 */ 227 WalkState->Op = NULL; 228 229 Status = WalkState->DescendingCallback (WalkState, Op); 230 if (ACPI_FAILURE (Status)) 231 { 232 ACPI_EXCEPTION ((AE_INFO, Status, "During name lookup/catalog")); 233 return_ACPI_STATUS (Status); 234 } 235 236 if (!*Op) 237 { 238 return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE); 239 } 240 241 Status = AcpiPsNextParseState (WalkState, *Op, Status); 242 if (ACPI_FAILURE (Status)) 243 { 244 if (Status == AE_CTRL_PENDING) 245 { 246 return_ACPI_STATUS (AE_CTRL_PARSE_PENDING); 247 } 248 return_ACPI_STATUS (Status); 249 } 250 251 AcpiPsAppendArg (*Op, UnnamedOp->Common.Value.Arg); 252 253 if ((*Op)->Common.AmlOpcode == AML_REGION_OP || 254 (*Op)->Common.AmlOpcode == AML_DATA_REGION_OP) 255 { 256 /* 257 * Defer final parsing of an OperationRegion body, because we don't 258 * have enough info in the first pass to parse it correctly (i.e., 259 * there may be method calls within the TermArg elements of the body.) 260 * 261 * However, we must continue parsing because the opregion is not a 262 * standalone package -- we don't know where the end is at this point. 263 * 264 * (Length is unknown until parse of the body complete) 265 */ 266 (*Op)->Named.Data = AmlOpStart; 267 (*Op)->Named.Length = 0; 268 } 269 270 return_ACPI_STATUS (AE_OK); 271 } 272 273 274 /******************************************************************************* 275 * 276 * FUNCTION: AcpiPsCreateOp 277 * 278 * PARAMETERS: WalkState - Current state 279 * AmlOpStart - Op start in AML 280 * NewOp - Returned Op 281 * 282 * RETURN: Status 283 * 284 * DESCRIPTION: Get Op from AML 285 * 286 ******************************************************************************/ 287 288 ACPI_STATUS 289 AcpiPsCreateOp ( 290 ACPI_WALK_STATE *WalkState, 291 UINT8 *AmlOpStart, 292 ACPI_PARSE_OBJECT **NewOp) 293 { 294 ACPI_STATUS Status = AE_OK; 295 ACPI_PARSE_OBJECT *Op; 296 ACPI_PARSE_OBJECT *NamedOp = NULL; 297 ACPI_PARSE_OBJECT *ParentScope; 298 UINT8 ArgumentCount; 299 const ACPI_OPCODE_INFO *OpInfo; 300 301 302 ACPI_FUNCTION_TRACE_PTR (PsCreateOp, WalkState); 303 304 305 Status = AcpiPsGetAmlOpcode (WalkState); 306 if (Status == AE_CTRL_PARSE_CONTINUE) 307 { 308 return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE); 309 } 310 311 /* Create Op structure and append to parent's argument list */ 312 313 WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode); 314 Op = AcpiPsAllocOp (WalkState->Opcode); 315 if (!Op) 316 { 317 return_ACPI_STATUS (AE_NO_MEMORY); 318 } 319 320 if (WalkState->OpInfo->Flags & AML_NAMED) 321 { 322 Status = AcpiPsBuildNamedOp (WalkState, AmlOpStart, Op, &NamedOp); 323 AcpiPsFreeOp (Op); 324 if (ACPI_FAILURE (Status)) 325 { 326 return_ACPI_STATUS (Status); 327 } 328 329 *NewOp = NamedOp; 330 return_ACPI_STATUS (AE_OK); 331 } 332 333 /* Not a named opcode, just allocate Op and append to parent */ 334 335 if (WalkState->OpInfo->Flags & AML_CREATE) 336 { 337 /* 338 * Backup to beginning of CreateXXXfield declaration 339 * BodyLength is unknown until we parse the body 340 */ 341 Op->Named.Data = AmlOpStart; 342 Op->Named.Length = 0; 343 } 344 345 if (WalkState->Opcode == AML_BANK_FIELD_OP) 346 { 347 /* 348 * Backup to beginning of BankField declaration 349 * BodyLength is unknown until we parse the body 350 */ 351 Op->Named.Data = AmlOpStart; 352 Op->Named.Length = 0; 353 } 354 355 ParentScope = AcpiPsGetParentScope (&(WalkState->ParserState)); 356 AcpiPsAppendArg (ParentScope, Op); 357 358 if (ParentScope) 359 { 360 OpInfo = AcpiPsGetOpcodeInfo (ParentScope->Common.AmlOpcode); 361 if (OpInfo->Flags & AML_HAS_TARGET) 362 { 363 ArgumentCount = AcpiPsGetArgumentCount (OpInfo->Type); 364 if (ParentScope->Common.ArgListLength > ArgumentCount) 365 { 366 Op->Common.Flags |= ACPI_PARSEOP_TARGET; 367 } 368 } 369 else if (ParentScope->Common.AmlOpcode == AML_INCREMENT_OP) 370 { 371 Op->Common.Flags |= ACPI_PARSEOP_TARGET; 372 } 373 } 374 375 if (WalkState->DescendingCallback != NULL) 376 { 377 /* 378 * Find the object. This will either insert the object into 379 * the namespace or simply look it up 380 */ 381 WalkState->Op = *NewOp = Op; 382 383 Status = WalkState->DescendingCallback (WalkState, &Op); 384 Status = AcpiPsNextParseState (WalkState, Op, Status); 385 if (Status == AE_CTRL_PENDING) 386 { 387 Status = AE_CTRL_PARSE_PENDING; 388 } 389 } 390 391 return_ACPI_STATUS (Status); 392 } 393 394 395 /******************************************************************************* 396 * 397 * FUNCTION: AcpiPsCompleteOp 398 * 399 * PARAMETERS: WalkState - Current state 400 * Op - Returned Op 401 * Status - Parse status before complete Op 402 * 403 * RETURN: Status 404 * 405 * DESCRIPTION: Complete Op 406 * 407 ******************************************************************************/ 408 409 ACPI_STATUS 410 AcpiPsCompleteOp ( 411 ACPI_WALK_STATE *WalkState, 412 ACPI_PARSE_OBJECT **Op, 413 ACPI_STATUS Status) 414 { 415 ACPI_STATUS Status2; 416 417 418 ACPI_FUNCTION_TRACE_PTR (PsCompleteOp, WalkState); 419 420 421 /* 422 * Finished one argument of the containing scope 423 */ 424 WalkState->ParserState.Scope->ParseScope.ArgCount--; 425 426 /* Close this Op (will result in parse subtree deletion) */ 427 428 Status2 = AcpiPsCompleteThisOp (WalkState, *Op); 429 if (ACPI_FAILURE (Status2)) 430 { 431 return_ACPI_STATUS (Status2); 432 } 433 434 *Op = NULL; 435 436 switch (Status) 437 { 438 case AE_OK: 439 break; 440 441 442 case AE_CTRL_TRANSFER: 443 444 /* We are about to transfer to a called method */ 445 446 WalkState->PrevOp = NULL; 447 WalkState->PrevArgTypes = WalkState->ArgTypes; 448 return_ACPI_STATUS (Status); 449 450 451 case AE_CTRL_END: 452 453 AcpiPsPopScope (&(WalkState->ParserState), Op, 454 &WalkState->ArgTypes, &WalkState->ArgCount); 455 456 if (*Op) 457 { 458 WalkState->Op = *Op; 459 WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode); 460 WalkState->Opcode = (*Op)->Common.AmlOpcode; 461 462 Status = WalkState->AscendingCallback (WalkState); 463 Status = AcpiPsNextParseState (WalkState, *Op, Status); 464 465 Status2 = AcpiPsCompleteThisOp (WalkState, *Op); 466 if (ACPI_FAILURE (Status2)) 467 { 468 return_ACPI_STATUS (Status2); 469 } 470 } 471 472 Status = AE_OK; 473 break; 474 475 476 case AE_CTRL_BREAK: 477 case AE_CTRL_CONTINUE: 478 479 /* Pop off scopes until we find the While */ 480 481 while (!(*Op) || ((*Op)->Common.AmlOpcode != AML_WHILE_OP)) 482 { 483 AcpiPsPopScope (&(WalkState->ParserState), Op, 484 &WalkState->ArgTypes, &WalkState->ArgCount); 485 } 486 487 /* Close this iteration of the While loop */ 488 489 WalkState->Op = *Op; 490 WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode); 491 WalkState->Opcode = (*Op)->Common.AmlOpcode; 492 493 Status = WalkState->AscendingCallback (WalkState); 494 Status = AcpiPsNextParseState (WalkState, *Op, Status); 495 496 Status2 = AcpiPsCompleteThisOp (WalkState, *Op); 497 if (ACPI_FAILURE (Status2)) 498 { 499 return_ACPI_STATUS (Status2); 500 } 501 502 Status = AE_OK; 503 break; 504 505 506 case AE_CTRL_TERMINATE: 507 508 /* Clean up */ 509 do 510 { 511 if (*Op) 512 { 513 Status2 = AcpiPsCompleteThisOp (WalkState, *Op); 514 if (ACPI_FAILURE (Status2)) 515 { 516 return_ACPI_STATUS (Status2); 517 } 518 519 AcpiUtDeleteGenericState ( 520 AcpiUtPopGenericState (&WalkState->ControlState)); 521 } 522 523 AcpiPsPopScope (&(WalkState->ParserState), Op, 524 &WalkState->ArgTypes, &WalkState->ArgCount); 525 526 } while (*Op); 527 528 return_ACPI_STATUS (AE_OK); 529 530 531 default: /* All other non-AE_OK status */ 532 533 do 534 { 535 if (*Op) 536 { 537 Status2 = AcpiPsCompleteThisOp (WalkState, *Op); 538 if (ACPI_FAILURE (Status2)) 539 { 540 return_ACPI_STATUS (Status2); 541 } 542 } 543 544 AcpiPsPopScope (&(WalkState->ParserState), Op, 545 &WalkState->ArgTypes, &WalkState->ArgCount); 546 547 } while (*Op); 548 549 550 #if 0 551 /* 552 * TBD: Cleanup parse ops on error 553 */ 554 if (*Op == NULL) 555 { 556 AcpiPsPopScope (ParserState, Op, 557 &WalkState->ArgTypes, &WalkState->ArgCount); 558 } 559 #endif 560 WalkState->PrevOp = NULL; 561 WalkState->PrevArgTypes = WalkState->ArgTypes; 562 return_ACPI_STATUS (Status); 563 } 564 565 /* This scope complete? */ 566 567 if (AcpiPsHasCompletedScope (&(WalkState->ParserState))) 568 { 569 AcpiPsPopScope (&(WalkState->ParserState), Op, 570 &WalkState->ArgTypes, &WalkState->ArgCount); 571 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *Op)); 572 } 573 else 574 { 575 *Op = NULL; 576 } 577 578 return_ACPI_STATUS (AE_OK); 579 } 580 581 582 /******************************************************************************* 583 * 584 * FUNCTION: AcpiPsCompleteFinalOp 585 * 586 * PARAMETERS: WalkState - Current state 587 * Op - Current Op 588 * Status - Current parse status before complete last 589 * Op 590 * 591 * RETURN: Status 592 * 593 * DESCRIPTION: Complete last Op. 594 * 595 ******************************************************************************/ 596 597 ACPI_STATUS 598 AcpiPsCompleteFinalOp ( 599 ACPI_WALK_STATE *WalkState, 600 ACPI_PARSE_OBJECT *Op, 601 ACPI_STATUS Status) 602 { 603 ACPI_STATUS Status2; 604 605 606 ACPI_FUNCTION_TRACE_PTR (PsCompleteFinalOp, WalkState); 607 608 609 /* 610 * Complete the last Op (if not completed), and clear the scope stack. 611 * It is easily possible to end an AML "package" with an unbounded number 612 * of open scopes (such as when several ASL blocks are closed with 613 * sequential closing braces). We want to terminate each one cleanly. 614 */ 615 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", Op)); 616 do 617 { 618 if (Op) 619 { 620 if (WalkState->AscendingCallback != NULL) 621 { 622 WalkState->Op = Op; 623 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 624 WalkState->Opcode = Op->Common.AmlOpcode; 625 626 Status = WalkState->AscendingCallback (WalkState); 627 Status = AcpiPsNextParseState (WalkState, Op, Status); 628 if (Status == AE_CTRL_PENDING) 629 { 630 Status = AcpiPsCompleteOp (WalkState, &Op, AE_OK); 631 if (ACPI_FAILURE (Status)) 632 { 633 return_ACPI_STATUS (Status); 634 } 635 } 636 637 if (Status == AE_CTRL_TERMINATE) 638 { 639 Status = AE_OK; 640 641 /* Clean up */ 642 do 643 { 644 if (Op) 645 { 646 Status2 = AcpiPsCompleteThisOp (WalkState, Op); 647 if (ACPI_FAILURE (Status2)) 648 { 649 return_ACPI_STATUS (Status2); 650 } 651 } 652 653 AcpiPsPopScope (&(WalkState->ParserState), &Op, 654 &WalkState->ArgTypes, &WalkState->ArgCount); 655 656 } while (Op); 657 658 return_ACPI_STATUS (Status); 659 } 660 661 else if (ACPI_FAILURE (Status)) 662 { 663 /* First error is most important */ 664 665 (void) AcpiPsCompleteThisOp (WalkState, Op); 666 return_ACPI_STATUS (Status); 667 } 668 } 669 670 Status2 = AcpiPsCompleteThisOp (WalkState, Op); 671 if (ACPI_FAILURE (Status2)) 672 { 673 return_ACPI_STATUS (Status2); 674 } 675 } 676 677 AcpiPsPopScope (&(WalkState->ParserState), &Op, &WalkState->ArgTypes, 678 &WalkState->ArgCount); 679 680 } while (Op); 681 682 return_ACPI_STATUS (Status); 683 } 684