1 /******************************************************************************* 2 * 3 * Module Name: dsutils - Dispatcher utilities 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 #define __DSUTILS_C__ 45 46 #include "acpi.h" 47 #include "accommon.h" 48 #include "acparser.h" 49 #include "amlcode.h" 50 #include "acdispat.h" 51 #include "acinterp.h" 52 #include "acnamesp.h" 53 #include "acdebug.h" 54 55 #define _COMPONENT ACPI_DISPATCHER 56 ACPI_MODULE_NAME ("dsutils") 57 58 59 /******************************************************************************* 60 * 61 * FUNCTION: AcpiDsClearImplicitReturn 62 * 63 * PARAMETERS: WalkState - Current State 64 * 65 * RETURN: None. 66 * 67 * DESCRIPTION: Clear and remove a reference on an implicit return value. Used 68 * to delete "stale" return values (if enabled, the return value 69 * from every operator is saved at least momentarily, in case the 70 * parent method exits.) 71 * 72 ******************************************************************************/ 73 74 void 75 AcpiDsClearImplicitReturn ( 76 ACPI_WALK_STATE *WalkState) 77 { 78 ACPI_FUNCTION_NAME (DsClearImplicitReturn); 79 80 81 /* 82 * Slack must be enabled for this feature 83 */ 84 if (!AcpiGbl_EnableInterpreterSlack) 85 { 86 return; 87 } 88 89 if (WalkState->ImplicitReturnObj) 90 { 91 /* 92 * Delete any "stale" implicit return. However, in 93 * complex statements, the implicit return value can be 94 * bubbled up several levels. 95 */ 96 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 97 "Removing reference on stale implicit return obj %p\n", 98 WalkState->ImplicitReturnObj)); 99 100 AcpiUtRemoveReference (WalkState->ImplicitReturnObj); 101 WalkState->ImplicitReturnObj = NULL; 102 } 103 } 104 105 106 #ifndef ACPI_NO_METHOD_EXECUTION 107 /******************************************************************************* 108 * 109 * FUNCTION: AcpiDsDoImplicitReturn 110 * 111 * PARAMETERS: ReturnDesc - The return value 112 * WalkState - Current State 113 * AddReference - True if a reference should be added to the 114 * return object 115 * 116 * RETURN: TRUE if implicit return enabled, FALSE otherwise 117 * 118 * DESCRIPTION: Implements the optional "implicit return". We save the result 119 * of every ASL operator and control method invocation in case the 120 * parent method exit. Before storing a new return value, we 121 * delete the previous return value. 122 * 123 ******************************************************************************/ 124 125 BOOLEAN 126 AcpiDsDoImplicitReturn ( 127 ACPI_OPERAND_OBJECT *ReturnDesc, 128 ACPI_WALK_STATE *WalkState, 129 BOOLEAN AddReference) 130 { 131 ACPI_FUNCTION_NAME (DsDoImplicitReturn); 132 133 134 /* 135 * Slack must be enabled for this feature, and we must 136 * have a valid return object 137 */ 138 if ((!AcpiGbl_EnableInterpreterSlack) || 139 (!ReturnDesc)) 140 { 141 return (FALSE); 142 } 143 144 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 145 "Result %p will be implicitly returned; Prev=%p\n", 146 ReturnDesc, 147 WalkState->ImplicitReturnObj)); 148 149 /* 150 * Delete any "stale" implicit return value first. However, in 151 * complex statements, the implicit return value can be 152 * bubbled up several levels, so we don't clear the value if it 153 * is the same as the ReturnDesc. 154 */ 155 if (WalkState->ImplicitReturnObj) 156 { 157 if (WalkState->ImplicitReturnObj == ReturnDesc) 158 { 159 return (TRUE); 160 } 161 AcpiDsClearImplicitReturn (WalkState); 162 } 163 164 /* Save the implicit return value, add a reference if requested */ 165 166 WalkState->ImplicitReturnObj = ReturnDesc; 167 if (AddReference) 168 { 169 AcpiUtAddReference (ReturnDesc); 170 } 171 172 return (TRUE); 173 } 174 175 176 /******************************************************************************* 177 * 178 * FUNCTION: AcpiDsIsResultUsed 179 * 180 * PARAMETERS: Op - Current Op 181 * WalkState - Current State 182 * 183 * RETURN: TRUE if result is used, FALSE otherwise 184 * 185 * DESCRIPTION: Check if a result object will be used by the parent 186 * 187 ******************************************************************************/ 188 189 BOOLEAN 190 AcpiDsIsResultUsed ( 191 ACPI_PARSE_OBJECT *Op, 192 ACPI_WALK_STATE *WalkState) 193 { 194 const ACPI_OPCODE_INFO *ParentInfo; 195 196 ACPI_FUNCTION_TRACE_PTR (DsIsResultUsed, Op); 197 198 199 /* Must have both an Op and a Result Object */ 200 201 if (!Op) 202 { 203 ACPI_ERROR ((AE_INFO, "Null Op")); 204 return_UINT8 (TRUE); 205 } 206 207 /* 208 * We know that this operator is not a 209 * Return() operator (would not come here.) The following code is the 210 * optional support for a so-called "implicit return". Some AML code 211 * assumes that the last value of the method is "implicitly" returned 212 * to the caller. Just save the last result as the return value. 213 * NOTE: this is optional because the ASL language does not actually 214 * support this behavior. 215 */ 216 (void) AcpiDsDoImplicitReturn (WalkState->ResultObj, WalkState, TRUE); 217 218 /* 219 * Now determine if the parent will use the result 220 * 221 * If there is no parent, or the parent is a ScopeOp, we are executing 222 * at the method level. An executing method typically has no parent, 223 * since each method is parsed separately. A method invoked externally 224 * via ExecuteControlMethod has a ScopeOp as the parent. 225 */ 226 if ((!Op->Common.Parent) || 227 (Op->Common.Parent->Common.AmlOpcode == AML_SCOPE_OP)) 228 { 229 /* No parent, the return value cannot possibly be used */ 230 231 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 232 "At Method level, result of [%s] not used\n", 233 AcpiPsGetOpcodeName (Op->Common.AmlOpcode))); 234 return_UINT8 (FALSE); 235 } 236 237 /* Get info on the parent. The RootOp is AML_SCOPE */ 238 239 ParentInfo = AcpiPsGetOpcodeInfo (Op->Common.Parent->Common.AmlOpcode); 240 if (ParentInfo->Class == AML_CLASS_UNKNOWN) 241 { 242 ACPI_ERROR ((AE_INFO, 243 "Unknown parent opcode Op=%p", Op)); 244 return_UINT8 (FALSE); 245 } 246 247 /* 248 * Decide what to do with the result based on the parent. If 249 * the parent opcode will not use the result, delete the object. 250 * Otherwise leave it as is, it will be deleted when it is used 251 * as an operand later. 252 */ 253 switch (ParentInfo->Class) 254 { 255 case AML_CLASS_CONTROL: 256 257 switch (Op->Common.Parent->Common.AmlOpcode) 258 { 259 case AML_RETURN_OP: 260 261 /* Never delete the return value associated with a return opcode */ 262 263 goto ResultUsed; 264 265 case AML_IF_OP: 266 case AML_WHILE_OP: 267 268 /* 269 * If we are executing the predicate AND this is the predicate op, 270 * we will use the return value 271 */ 272 if ((WalkState->ControlState->Common.State == ACPI_CONTROL_PREDICATE_EXECUTING) && 273 (WalkState->ControlState->Control.PredicateOp == Op)) 274 { 275 goto ResultUsed; 276 } 277 break; 278 279 default: 280 /* Ignore other control opcodes */ 281 break; 282 } 283 284 /* The general control opcode returns no result */ 285 286 goto ResultNotUsed; 287 288 289 case AML_CLASS_CREATE: 290 291 /* 292 * These opcodes allow TermArg(s) as operands and therefore 293 * the operands can be method calls. The result is used. 294 */ 295 goto ResultUsed; 296 297 298 case AML_CLASS_NAMED_OBJECT: 299 300 if ((Op->Common.Parent->Common.AmlOpcode == AML_REGION_OP) || 301 (Op->Common.Parent->Common.AmlOpcode == AML_DATA_REGION_OP) || 302 (Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || 303 (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP) || 304 (Op->Common.Parent->Common.AmlOpcode == AML_BUFFER_OP) || 305 (Op->Common.Parent->Common.AmlOpcode == AML_INT_EVAL_SUBTREE_OP) || 306 (Op->Common.Parent->Common.AmlOpcode == AML_BANK_FIELD_OP)) 307 { 308 /* 309 * These opcodes allow TermArg(s) as operands and therefore 310 * the operands can be method calls. The result is used. 311 */ 312 goto ResultUsed; 313 } 314 315 goto ResultNotUsed; 316 317 318 default: 319 320 /* 321 * In all other cases. the parent will actually use the return 322 * object, so keep it. 323 */ 324 goto ResultUsed; 325 } 326 327 328 ResultUsed: 329 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 330 "Result of [%s] used by Parent [%s] Op=%p\n", 331 AcpiPsGetOpcodeName (Op->Common.AmlOpcode), 332 AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op)); 333 334 return_UINT8 (TRUE); 335 336 337 ResultNotUsed: 338 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 339 "Result of [%s] not used by Parent [%s] Op=%p\n", 340 AcpiPsGetOpcodeName (Op->Common.AmlOpcode), 341 AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op)); 342 343 return_UINT8 (FALSE); 344 } 345 346 347 /******************************************************************************* 348 * 349 * FUNCTION: AcpiDsDeleteResultIfNotUsed 350 * 351 * PARAMETERS: Op - Current parse Op 352 * ResultObj - Result of the operation 353 * WalkState - Current state 354 * 355 * RETURN: Status 356 * 357 * DESCRIPTION: Used after interpretation of an opcode. If there is an internal 358 * result descriptor, check if the parent opcode will actually use 359 * this result. If not, delete the result now so that it will 360 * not become orphaned. 361 * 362 ******************************************************************************/ 363 364 void 365 AcpiDsDeleteResultIfNotUsed ( 366 ACPI_PARSE_OBJECT *Op, 367 ACPI_OPERAND_OBJECT *ResultObj, 368 ACPI_WALK_STATE *WalkState) 369 { 370 ACPI_OPERAND_OBJECT *ObjDesc; 371 ACPI_STATUS Status; 372 373 374 ACPI_FUNCTION_TRACE_PTR (DsDeleteResultIfNotUsed, ResultObj); 375 376 377 if (!Op) 378 { 379 ACPI_ERROR ((AE_INFO, "Null Op")); 380 return_VOID; 381 } 382 383 if (!ResultObj) 384 { 385 return_VOID; 386 } 387 388 if (!AcpiDsIsResultUsed (Op, WalkState)) 389 { 390 /* Must pop the result stack (ObjDesc should be equal to ResultObj) */ 391 392 Status = AcpiDsResultPop (&ObjDesc, WalkState); 393 if (ACPI_SUCCESS (Status)) 394 { 395 AcpiUtRemoveReference (ResultObj); 396 } 397 } 398 399 return_VOID; 400 } 401 402 403 /******************************************************************************* 404 * 405 * FUNCTION: AcpiDsResolveOperands 406 * 407 * PARAMETERS: WalkState - Current walk state with operands on stack 408 * 409 * RETURN: Status 410 * 411 * DESCRIPTION: Resolve all operands to their values. Used to prepare 412 * arguments to a control method invocation (a call from one 413 * method to another.) 414 * 415 ******************************************************************************/ 416 417 ACPI_STATUS 418 AcpiDsResolveOperands ( 419 ACPI_WALK_STATE *WalkState) 420 { 421 UINT32 i; 422 ACPI_STATUS Status = AE_OK; 423 424 425 ACPI_FUNCTION_TRACE_PTR (DsResolveOperands, WalkState); 426 427 428 /* 429 * Attempt to resolve each of the valid operands 430 * Method arguments are passed by reference, not by value. This means 431 * that the actual objects are passed, not copies of the objects. 432 */ 433 for (i = 0; i < WalkState->NumOperands; i++) 434 { 435 Status = AcpiExResolveToValue (&WalkState->Operands[i], WalkState); 436 if (ACPI_FAILURE (Status)) 437 { 438 break; 439 } 440 } 441 442 return_ACPI_STATUS (Status); 443 } 444 445 446 /******************************************************************************* 447 * 448 * FUNCTION: AcpiDsClearOperands 449 * 450 * PARAMETERS: WalkState - Current walk state with operands on stack 451 * 452 * RETURN: None 453 * 454 * DESCRIPTION: Clear all operands on the current walk state operand stack. 455 * 456 ******************************************************************************/ 457 458 void 459 AcpiDsClearOperands ( 460 ACPI_WALK_STATE *WalkState) 461 { 462 UINT32 i; 463 464 465 ACPI_FUNCTION_TRACE_PTR (DsClearOperands, WalkState); 466 467 468 /* Remove a reference on each operand on the stack */ 469 470 for (i = 0; i < WalkState->NumOperands; i++) 471 { 472 /* 473 * Remove a reference to all operands, including both 474 * "Arguments" and "Targets". 475 */ 476 AcpiUtRemoveReference (WalkState->Operands[i]); 477 WalkState->Operands[i] = NULL; 478 } 479 480 WalkState->NumOperands = 0; 481 return_VOID; 482 } 483 #endif 484 485 486 /******************************************************************************* 487 * 488 * FUNCTION: AcpiDsCreateOperand 489 * 490 * PARAMETERS: WalkState - Current walk state 491 * Arg - Parse object for the argument 492 * ArgIndex - Which argument (zero based) 493 * 494 * RETURN: Status 495 * 496 * DESCRIPTION: Translate a parse tree object that is an argument to an AML 497 * opcode to the equivalent interpreter object. This may include 498 * looking up a name or entering a new name into the internal 499 * namespace. 500 * 501 ******************************************************************************/ 502 503 ACPI_STATUS 504 AcpiDsCreateOperand ( 505 ACPI_WALK_STATE *WalkState, 506 ACPI_PARSE_OBJECT *Arg, 507 UINT32 ArgIndex) 508 { 509 ACPI_STATUS Status = AE_OK; 510 char *NameString; 511 UINT32 NameLength; 512 ACPI_OPERAND_OBJECT *ObjDesc; 513 ACPI_PARSE_OBJECT *ParentOp; 514 UINT16 Opcode; 515 ACPI_INTERPRETER_MODE InterpreterMode; 516 const ACPI_OPCODE_INFO *OpInfo; 517 518 519 ACPI_FUNCTION_TRACE_PTR (DsCreateOperand, Arg); 520 521 522 /* A valid name must be looked up in the namespace */ 523 524 if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && 525 (Arg->Common.Value.String) && 526 !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK)) 527 { 528 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", Arg)); 529 530 /* Get the entire name string from the AML stream */ 531 532 Status = AcpiExGetNameString (ACPI_TYPE_ANY, Arg->Common.Value.Buffer, 533 &NameString, &NameLength); 534 535 if (ACPI_FAILURE (Status)) 536 { 537 return_ACPI_STATUS (Status); 538 } 539 540 /* All prefixes have been handled, and the name is in NameString */ 541 542 /* 543 * Special handling for BufferField declarations. This is a deferred 544 * opcode that unfortunately defines the field name as the last 545 * parameter instead of the first. We get here when we are performing 546 * the deferred execution, so the actual name of the field is already 547 * in the namespace. We don't want to attempt to look it up again 548 * because we may be executing in a different scope than where the 549 * actual opcode exists. 550 */ 551 if ((WalkState->DeferredNode) && 552 (WalkState->DeferredNode->Type == ACPI_TYPE_BUFFER_FIELD) && 553 (ArgIndex == (UINT32) ((WalkState->Opcode == AML_CREATE_FIELD_OP) ? 3 : 2))) 554 { 555 ObjDesc = ACPI_CAST_PTR ( 556 ACPI_OPERAND_OBJECT, WalkState->DeferredNode); 557 Status = AE_OK; 558 } 559 else /* All other opcodes */ 560 { 561 /* 562 * Differentiate between a namespace "create" operation 563 * versus a "lookup" operation (IMODE_LOAD_PASS2 vs. 564 * IMODE_EXECUTE) in order to support the creation of 565 * namespace objects during the execution of control methods. 566 */ 567 ParentOp = Arg->Common.Parent; 568 OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode); 569 if ((OpInfo->Flags & AML_NSNODE) && 570 (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) && 571 (ParentOp->Common.AmlOpcode != AML_REGION_OP) && 572 (ParentOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP)) 573 { 574 /* Enter name into namespace if not found */ 575 576 InterpreterMode = ACPI_IMODE_LOAD_PASS2; 577 } 578 else 579 { 580 /* Return a failure if name not found */ 581 582 InterpreterMode = ACPI_IMODE_EXECUTE; 583 } 584 585 Status = AcpiNsLookup (WalkState->ScopeInfo, NameString, 586 ACPI_TYPE_ANY, InterpreterMode, 587 ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, 588 WalkState, 589 ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &ObjDesc)); 590 /* 591 * The only case where we pass through (ignore) a NOT_FOUND 592 * error is for the CondRefOf opcode. 593 */ 594 if (Status == AE_NOT_FOUND) 595 { 596 if (ParentOp->Common.AmlOpcode == AML_COND_REF_OF_OP) 597 { 598 /* 599 * For the Conditional Reference op, it's OK if 600 * the name is not found; We just need a way to 601 * indicate this to the interpreter, set the 602 * object to the root 603 */ 604 ObjDesc = ACPI_CAST_PTR ( 605 ACPI_OPERAND_OBJECT, AcpiGbl_RootNode); 606 Status = AE_OK; 607 } 608 else 609 { 610 /* 611 * We just plain didn't find it -- which is a 612 * very serious error at this point 613 */ 614 Status = AE_AML_NAME_NOT_FOUND; 615 } 616 } 617 618 if (ACPI_FAILURE (Status)) 619 { 620 ACPI_ERROR_NAMESPACE (NameString, Status); 621 } 622 } 623 624 /* Free the namestring created above */ 625 626 ACPI_FREE (NameString); 627 628 /* Check status from the lookup */ 629 630 if (ACPI_FAILURE (Status)) 631 { 632 return_ACPI_STATUS (Status); 633 } 634 635 /* Put the resulting object onto the current object stack */ 636 637 Status = AcpiDsObjStackPush (ObjDesc, WalkState); 638 if (ACPI_FAILURE (Status)) 639 { 640 return_ACPI_STATUS (Status); 641 } 642 ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState)); 643 } 644 else 645 { 646 /* Check for null name case */ 647 648 if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && 649 !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK)) 650 { 651 /* 652 * If the name is null, this means that this is an 653 * optional result parameter that was not specified 654 * in the original ASL. Create a Zero Constant for a 655 * placeholder. (Store to a constant is a Noop.) 656 */ 657 Opcode = AML_ZERO_OP; /* Has no arguments! */ 658 659 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 660 "Null namepath: Arg=%p\n", Arg)); 661 } 662 else 663 { 664 Opcode = Arg->Common.AmlOpcode; 665 } 666 667 /* Get the object type of the argument */ 668 669 OpInfo = AcpiPsGetOpcodeInfo (Opcode); 670 if (OpInfo->ObjectType == ACPI_TYPE_INVALID) 671 { 672 return_ACPI_STATUS (AE_NOT_IMPLEMENTED); 673 } 674 675 if ((OpInfo->Flags & AML_HAS_RETVAL) || (Arg->Common.Flags & ACPI_PARSEOP_IN_STACK)) 676 { 677 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 678 "Argument previously created, already stacked\n")); 679 680 ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject ( 681 WalkState->Operands [WalkState->NumOperands - 1], WalkState)); 682 683 /* 684 * Use value that was already previously returned 685 * by the evaluation of this argument 686 */ 687 Status = AcpiDsResultPop (&ObjDesc, WalkState); 688 if (ACPI_FAILURE (Status)) 689 { 690 /* 691 * Only error is underflow, and this indicates 692 * a missing or null operand! 693 */ 694 ACPI_EXCEPTION ((AE_INFO, Status, 695 "Missing or null operand")); 696 return_ACPI_STATUS (Status); 697 } 698 } 699 else 700 { 701 /* Create an ACPI_INTERNAL_OBJECT for the argument */ 702 703 ObjDesc = AcpiUtCreateInternalObject (OpInfo->ObjectType); 704 if (!ObjDesc) 705 { 706 return_ACPI_STATUS (AE_NO_MEMORY); 707 } 708 709 /* Initialize the new object */ 710 711 Status = AcpiDsInitObjectFromOp ( 712 WalkState, Arg, Opcode, &ObjDesc); 713 if (ACPI_FAILURE (Status)) 714 { 715 AcpiUtDeleteObjectDesc (ObjDesc); 716 return_ACPI_STATUS (Status); 717 } 718 } 719 720 /* Put the operand object on the object stack */ 721 722 Status = AcpiDsObjStackPush (ObjDesc, WalkState); 723 if (ACPI_FAILURE (Status)) 724 { 725 return_ACPI_STATUS (Status); 726 } 727 728 ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState)); 729 } 730 731 return_ACPI_STATUS (AE_OK); 732 } 733 734 735 /******************************************************************************* 736 * 737 * FUNCTION: AcpiDsCreateOperands 738 * 739 * PARAMETERS: WalkState - Current state 740 * FirstArg - First argument of a parser argument tree 741 * 742 * RETURN: Status 743 * 744 * DESCRIPTION: Convert an operator's arguments from a parse tree format to 745 * namespace objects and place those argument object on the object 746 * stack in preparation for evaluation by the interpreter. 747 * 748 ******************************************************************************/ 749 750 ACPI_STATUS 751 AcpiDsCreateOperands ( 752 ACPI_WALK_STATE *WalkState, 753 ACPI_PARSE_OBJECT *FirstArg) 754 { 755 ACPI_STATUS Status = AE_OK; 756 ACPI_PARSE_OBJECT *Arg; 757 ACPI_PARSE_OBJECT *Arguments[ACPI_OBJ_NUM_OPERANDS]; 758 UINT32 ArgCount = 0; 759 UINT32 Index = WalkState->NumOperands; 760 UINT32 i; 761 762 763 ACPI_FUNCTION_TRACE_PTR (DsCreateOperands, FirstArg); 764 765 766 /* Get all arguments in the list */ 767 768 Arg = FirstArg; 769 while (Arg) 770 { 771 if (Index >= ACPI_OBJ_NUM_OPERANDS) 772 { 773 return_ACPI_STATUS (AE_BAD_DATA); 774 } 775 776 Arguments[Index] = Arg; 777 WalkState->Operands [Index] = NULL; 778 779 /* Move on to next argument, if any */ 780 781 Arg = Arg->Common.Next; 782 ArgCount++; 783 Index++; 784 } 785 786 Index--; 787 788 /* It is the appropriate order to get objects from the Result stack */ 789 790 for (i = 0; i < ArgCount; i++) 791 { 792 Arg = Arguments[Index]; 793 794 /* Force the filling of the operand stack in inverse order */ 795 796 WalkState->OperandIndex = (UINT8) Index; 797 798 Status = AcpiDsCreateOperand (WalkState, Arg, Index); 799 if (ACPI_FAILURE (Status)) 800 { 801 goto Cleanup; 802 } 803 804 Index--; 805 806 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Arg #%u (%p) done, Arg1=%p\n", 807 Index, Arg, FirstArg)); 808 } 809 810 return_ACPI_STATUS (Status); 811 812 813 Cleanup: 814 /* 815 * We must undo everything done above; meaning that we must 816 * pop everything off of the operand stack and delete those 817 * objects 818 */ 819 AcpiDsObjStackPopAndDelete (ArgCount, WalkState); 820 821 ACPI_EXCEPTION ((AE_INFO, Status, "While creating Arg %u", Index)); 822 return_ACPI_STATUS (Status); 823 } 824 825 826 /***************************************************************************** 827 * 828 * FUNCTION: AcpiDsEvaluateNamePath 829 * 830 * PARAMETERS: WalkState - Current state of the parse tree walk, 831 * the opcode of current operation should be 832 * AML_INT_NAMEPATH_OP 833 * 834 * RETURN: Status 835 * 836 * DESCRIPTION: Translate the -NamePath- parse tree object to the equivalent 837 * interpreter object, convert it to value, if needed, duplicate 838 * it, if needed, and push it onto the current result stack. 839 * 840 ****************************************************************************/ 841 842 ACPI_STATUS 843 AcpiDsEvaluateNamePath ( 844 ACPI_WALK_STATE *WalkState) 845 { 846 ACPI_STATUS Status = AE_OK; 847 ACPI_PARSE_OBJECT *Op = WalkState->Op; 848 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 849 ACPI_OPERAND_OBJECT *NewObjDesc; 850 UINT8 Type; 851 852 853 ACPI_FUNCTION_TRACE_PTR (DsEvaluateNamePath, WalkState); 854 855 856 if (!Op->Common.Parent) 857 { 858 /* This happens after certain exception processing */ 859 860 goto Exit; 861 } 862 863 if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || 864 (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP) || 865 (Op->Common.Parent->Common.AmlOpcode == AML_REF_OF_OP)) 866 { 867 /* TBD: Should we specify this feature as a bit of OpInfo->Flags of these opcodes? */ 868 869 goto Exit; 870 } 871 872 Status = AcpiDsCreateOperand (WalkState, Op, 0); 873 if (ACPI_FAILURE (Status)) 874 { 875 goto Exit; 876 } 877 878 if (Op->Common.Flags & ACPI_PARSEOP_TARGET) 879 { 880 NewObjDesc = *Operand; 881 goto PushResult; 882 } 883 884 Type = (*Operand)->Common.Type; 885 886 Status = AcpiExResolveToValue (Operand, WalkState); 887 if (ACPI_FAILURE (Status)) 888 { 889 goto Exit; 890 } 891 892 if (Type == ACPI_TYPE_INTEGER) 893 { 894 /* It was incremented by AcpiExResolveToValue */ 895 896 AcpiUtRemoveReference (*Operand); 897 898 Status = AcpiUtCopyIobjectToIobject (*Operand, &NewObjDesc, WalkState); 899 if (ACPI_FAILURE (Status)) 900 { 901 goto Exit; 902 } 903 } 904 else 905 { 906 /* 907 * The object either was anew created or is 908 * a Namespace node - don't decrement it. 909 */ 910 NewObjDesc = *Operand; 911 } 912 913 /* Cleanup for name-path operand */ 914 915 Status = AcpiDsObjStackPop (1, WalkState); 916 if (ACPI_FAILURE (Status)) 917 { 918 WalkState->ResultObj = NewObjDesc; 919 goto Exit; 920 } 921 922 PushResult: 923 924 WalkState->ResultObj = NewObjDesc; 925 926 Status = AcpiDsResultPush (WalkState->ResultObj, WalkState); 927 if (ACPI_SUCCESS (Status)) 928 { 929 /* Force to take it from stack */ 930 931 Op->Common.Flags |= ACPI_PARSEOP_IN_STACK; 932 } 933 934 Exit: 935 936 return_ACPI_STATUS (Status); 937 } 938