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