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