1 /******************************************************************************* 2 * 3 * Module Name: dsutils - Dispatcher utilities 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 #define __DSUTILS_C__ 45 46 #include <contrib/dev/acpica/include/acpi.h> 47 #include <contrib/dev/acpica/include/accommon.h> 48 #include <contrib/dev/acpica/include/acparser.h> 49 #include <contrib/dev/acpica/include/amlcode.h> 50 #include <contrib/dev/acpica/include/acdispat.h> 51 #include <contrib/dev/acpica/include/acinterp.h> 52 #include <contrib/dev/acpica/include/acnamesp.h> 53 #include <contrib/dev/acpica/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 * If we are executing the predicate AND this is the predicate op, 269 * we will use the return value 270 */ 271 if ((WalkState->ControlState->Common.State == ACPI_CONTROL_PREDICATE_EXECUTING) && 272 (WalkState->ControlState->Control.PredicateOp == Op)) 273 { 274 goto ResultUsed; 275 } 276 break; 277 278 default: 279 280 /* Ignore other control opcodes */ 281 282 break; 283 } 284 285 /* The general control opcode returns no result */ 286 287 goto ResultNotUsed; 288 289 case AML_CLASS_CREATE: 290 /* 291 * These opcodes allow TermArg(s) as operands and therefore 292 * the operands can be method calls. The result is used. 293 */ 294 goto ResultUsed; 295 296 case AML_CLASS_NAMED_OBJECT: 297 298 if ((Op->Common.Parent->Common.AmlOpcode == AML_REGION_OP) || 299 (Op->Common.Parent->Common.AmlOpcode == AML_DATA_REGION_OP) || 300 (Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || 301 (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP) || 302 (Op->Common.Parent->Common.AmlOpcode == AML_BUFFER_OP) || 303 (Op->Common.Parent->Common.AmlOpcode == AML_INT_EVAL_SUBTREE_OP) || 304 (Op->Common.Parent->Common.AmlOpcode == AML_BANK_FIELD_OP)) 305 { 306 /* 307 * These opcodes allow TermArg(s) as operands and therefore 308 * the operands can be method calls. The result is used. 309 */ 310 goto ResultUsed; 311 } 312 313 goto ResultNotUsed; 314 315 default: 316 /* 317 * In all other cases. the parent will actually use the return 318 * object, so keep it. 319 */ 320 goto ResultUsed; 321 } 322 323 324 ResultUsed: 325 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 326 "Result of [%s] used by Parent [%s] Op=%p\n", 327 AcpiPsGetOpcodeName (Op->Common.AmlOpcode), 328 AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op)); 329 330 return_UINT8 (TRUE); 331 332 333 ResultNotUsed: 334 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 335 "Result of [%s] not used by Parent [%s] Op=%p\n", 336 AcpiPsGetOpcodeName (Op->Common.AmlOpcode), 337 AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op)); 338 339 return_UINT8 (FALSE); 340 } 341 342 343 /******************************************************************************* 344 * 345 * FUNCTION: AcpiDsDeleteResultIfNotUsed 346 * 347 * PARAMETERS: Op - Current parse Op 348 * ResultObj - Result of the operation 349 * WalkState - Current state 350 * 351 * RETURN: Status 352 * 353 * DESCRIPTION: Used after interpretation of an opcode. If there is an internal 354 * result descriptor, check if the parent opcode will actually use 355 * this result. If not, delete the result now so that it will 356 * not become orphaned. 357 * 358 ******************************************************************************/ 359 360 void 361 AcpiDsDeleteResultIfNotUsed ( 362 ACPI_PARSE_OBJECT *Op, 363 ACPI_OPERAND_OBJECT *ResultObj, 364 ACPI_WALK_STATE *WalkState) 365 { 366 ACPI_OPERAND_OBJECT *ObjDesc; 367 ACPI_STATUS Status; 368 369 370 ACPI_FUNCTION_TRACE_PTR (DsDeleteResultIfNotUsed, ResultObj); 371 372 373 if (!Op) 374 { 375 ACPI_ERROR ((AE_INFO, "Null Op")); 376 return_VOID; 377 } 378 379 if (!ResultObj) 380 { 381 return_VOID; 382 } 383 384 if (!AcpiDsIsResultUsed (Op, WalkState)) 385 { 386 /* Must pop the result stack (ObjDesc should be equal to ResultObj) */ 387 388 Status = AcpiDsResultPop (&ObjDesc, WalkState); 389 if (ACPI_SUCCESS (Status)) 390 { 391 AcpiUtRemoveReference (ResultObj); 392 } 393 } 394 395 return_VOID; 396 } 397 398 399 /******************************************************************************* 400 * 401 * FUNCTION: AcpiDsResolveOperands 402 * 403 * PARAMETERS: WalkState - Current walk state with operands on stack 404 * 405 * RETURN: Status 406 * 407 * DESCRIPTION: Resolve all operands to their values. Used to prepare 408 * arguments to a control method invocation (a call from one 409 * method to another.) 410 * 411 ******************************************************************************/ 412 413 ACPI_STATUS 414 AcpiDsResolveOperands ( 415 ACPI_WALK_STATE *WalkState) 416 { 417 UINT32 i; 418 ACPI_STATUS Status = AE_OK; 419 420 421 ACPI_FUNCTION_TRACE_PTR (DsResolveOperands, WalkState); 422 423 424 /* 425 * Attempt to resolve each of the valid operands 426 * Method arguments are passed by reference, not by value. This means 427 * that the actual objects are passed, not copies of the objects. 428 */ 429 for (i = 0; i < WalkState->NumOperands; i++) 430 { 431 Status = AcpiExResolveToValue (&WalkState->Operands[i], WalkState); 432 if (ACPI_FAILURE (Status)) 433 { 434 break; 435 } 436 } 437 438 return_ACPI_STATUS (Status); 439 } 440 441 442 /******************************************************************************* 443 * 444 * FUNCTION: AcpiDsClearOperands 445 * 446 * PARAMETERS: WalkState - Current walk state with operands on stack 447 * 448 * RETURN: None 449 * 450 * DESCRIPTION: Clear all operands on the current walk state operand stack. 451 * 452 ******************************************************************************/ 453 454 void 455 AcpiDsClearOperands ( 456 ACPI_WALK_STATE *WalkState) 457 { 458 UINT32 i; 459 460 461 ACPI_FUNCTION_TRACE_PTR (DsClearOperands, WalkState); 462 463 464 /* Remove a reference on each operand on the stack */ 465 466 for (i = 0; i < WalkState->NumOperands; i++) 467 { 468 /* 469 * Remove a reference to all operands, including both 470 * "Arguments" and "Targets". 471 */ 472 AcpiUtRemoveReference (WalkState->Operands[i]); 473 WalkState->Operands[i] = NULL; 474 } 475 476 WalkState->NumOperands = 0; 477 return_VOID; 478 } 479 #endif 480 481 482 /******************************************************************************* 483 * 484 * FUNCTION: AcpiDsCreateOperand 485 * 486 * PARAMETERS: WalkState - Current walk state 487 * Arg - Parse object for the argument 488 * ArgIndex - Which argument (zero based) 489 * 490 * RETURN: Status 491 * 492 * DESCRIPTION: Translate a parse tree object that is an argument to an AML 493 * opcode to the equivalent interpreter object. This may include 494 * looking up a name or entering a new name into the internal 495 * namespace. 496 * 497 ******************************************************************************/ 498 499 ACPI_STATUS 500 AcpiDsCreateOperand ( 501 ACPI_WALK_STATE *WalkState, 502 ACPI_PARSE_OBJECT *Arg, 503 UINT32 ArgIndex) 504 { 505 ACPI_STATUS Status = AE_OK; 506 char *NameString; 507 UINT32 NameLength; 508 ACPI_OPERAND_OBJECT *ObjDesc; 509 ACPI_PARSE_OBJECT *ParentOp; 510 UINT16 Opcode; 511 ACPI_INTERPRETER_MODE InterpreterMode; 512 const ACPI_OPCODE_INFO *OpInfo; 513 514 515 ACPI_FUNCTION_TRACE_PTR (DsCreateOperand, Arg); 516 517 518 /* A valid name must be looked up in the namespace */ 519 520 if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && 521 (Arg->Common.Value.String) && 522 !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK)) 523 { 524 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", Arg)); 525 526 /* Get the entire name string from the AML stream */ 527 528 Status = AcpiExGetNameString (ACPI_TYPE_ANY, Arg->Common.Value.Buffer, 529 &NameString, &NameLength); 530 531 if (ACPI_FAILURE (Status)) 532 { 533 return_ACPI_STATUS (Status); 534 } 535 536 /* All prefixes have been handled, and the name is in NameString */ 537 538 /* 539 * Special handling for BufferField declarations. This is a deferred 540 * opcode that unfortunately defines the field name as the last 541 * parameter instead of the first. We get here when we are performing 542 * the deferred execution, so the actual name of the field is already 543 * in the namespace. We don't want to attempt to look it up again 544 * because we may be executing in a different scope than where the 545 * actual opcode exists. 546 */ 547 if ((WalkState->DeferredNode) && 548 (WalkState->DeferredNode->Type == ACPI_TYPE_BUFFER_FIELD) && 549 (ArgIndex == (UINT32) ((WalkState->Opcode == AML_CREATE_FIELD_OP) ? 3 : 2))) 550 { 551 ObjDesc = ACPI_CAST_PTR ( 552 ACPI_OPERAND_OBJECT, WalkState->DeferredNode); 553 Status = AE_OK; 554 } 555 else /* All other opcodes */ 556 { 557 /* 558 * Differentiate between a namespace "create" operation 559 * versus a "lookup" operation (IMODE_LOAD_PASS2 vs. 560 * IMODE_EXECUTE) in order to support the creation of 561 * namespace objects during the execution of control methods. 562 */ 563 ParentOp = Arg->Common.Parent; 564 OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode); 565 if ((OpInfo->Flags & AML_NSNODE) && 566 (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) && 567 (ParentOp->Common.AmlOpcode != AML_REGION_OP) && 568 (ParentOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP)) 569 { 570 /* Enter name into namespace if not found */ 571 572 InterpreterMode = ACPI_IMODE_LOAD_PASS2; 573 } 574 else 575 { 576 /* Return a failure if name not found */ 577 578 InterpreterMode = ACPI_IMODE_EXECUTE; 579 } 580 581 Status = AcpiNsLookup (WalkState->ScopeInfo, NameString, 582 ACPI_TYPE_ANY, InterpreterMode, 583 ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, 584 WalkState, 585 ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &ObjDesc)); 586 /* 587 * The only case where we pass through (ignore) a NOT_FOUND 588 * error is for the CondRefOf opcode. 589 */ 590 if (Status == AE_NOT_FOUND) 591 { 592 if (ParentOp->Common.AmlOpcode == AML_COND_REF_OF_OP) 593 { 594 /* 595 * For the Conditional Reference op, it's OK if 596 * the name is not found; We just need a way to 597 * indicate this to the interpreter, set the 598 * object to the root 599 */ 600 ObjDesc = ACPI_CAST_PTR ( 601 ACPI_OPERAND_OBJECT, AcpiGbl_RootNode); 602 Status = AE_OK; 603 } 604 else 605 { 606 /* 607 * We just plain didn't find it -- which is a 608 * very serious error at this point 609 */ 610 Status = AE_AML_NAME_NOT_FOUND; 611 } 612 } 613 614 if (ACPI_FAILURE (Status)) 615 { 616 ACPI_ERROR_NAMESPACE (NameString, Status); 617 } 618 } 619 620 /* Free the namestring created above */ 621 622 ACPI_FREE (NameString); 623 624 /* Check status from the lookup */ 625 626 if (ACPI_FAILURE (Status)) 627 { 628 return_ACPI_STATUS (Status); 629 } 630 631 /* Put the resulting object onto the current object stack */ 632 633 Status = AcpiDsObjStackPush (ObjDesc, WalkState); 634 if (ACPI_FAILURE (Status)) 635 { 636 return_ACPI_STATUS (Status); 637 } 638 ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState)); 639 } 640 else 641 { 642 /* Check for null name case */ 643 644 if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && 645 !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK)) 646 { 647 /* 648 * If the name is null, this means that this is an 649 * optional result parameter that was not specified 650 * in the original ASL. Create a Zero Constant for a 651 * placeholder. (Store to a constant is a Noop.) 652 */ 653 Opcode = AML_ZERO_OP; /* Has no arguments! */ 654 655 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 656 "Null namepath: Arg=%p\n", Arg)); 657 } 658 else 659 { 660 Opcode = Arg->Common.AmlOpcode; 661 } 662 663 /* Get the object type of the argument */ 664 665 OpInfo = AcpiPsGetOpcodeInfo (Opcode); 666 if (OpInfo->ObjectType == ACPI_TYPE_INVALID) 667 { 668 return_ACPI_STATUS (AE_NOT_IMPLEMENTED); 669 } 670 671 if ((OpInfo->Flags & AML_HAS_RETVAL) || (Arg->Common.Flags & ACPI_PARSEOP_IN_STACK)) 672 { 673 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 674 "Argument previously created, already stacked\n")); 675 676 ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject ( 677 WalkState->Operands [WalkState->NumOperands - 1], WalkState)); 678 679 /* 680 * Use value that was already previously returned 681 * by the evaluation of this argument 682 */ 683 Status = AcpiDsResultPop (&ObjDesc, WalkState); 684 if (ACPI_FAILURE (Status)) 685 { 686 /* 687 * Only error is underflow, and this indicates 688 * a missing or null operand! 689 */ 690 ACPI_EXCEPTION ((AE_INFO, Status, 691 "Missing or null operand")); 692 return_ACPI_STATUS (Status); 693 } 694 } 695 else 696 { 697 /* Create an ACPI_INTERNAL_OBJECT for the argument */ 698 699 ObjDesc = AcpiUtCreateInternalObject (OpInfo->ObjectType); 700 if (!ObjDesc) 701 { 702 return_ACPI_STATUS (AE_NO_MEMORY); 703 } 704 705 /* Initialize the new object */ 706 707 Status = AcpiDsInitObjectFromOp ( 708 WalkState, Arg, Opcode, &ObjDesc); 709 if (ACPI_FAILURE (Status)) 710 { 711 AcpiUtDeleteObjectDesc (ObjDesc); 712 return_ACPI_STATUS (Status); 713 } 714 } 715 716 /* Put the operand object on the object stack */ 717 718 Status = AcpiDsObjStackPush (ObjDesc, WalkState); 719 if (ACPI_FAILURE (Status)) 720 { 721 return_ACPI_STATUS (Status); 722 } 723 724 ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState)); 725 } 726 727 return_ACPI_STATUS (AE_OK); 728 } 729 730 731 /******************************************************************************* 732 * 733 * FUNCTION: AcpiDsCreateOperands 734 * 735 * PARAMETERS: WalkState - Current state 736 * FirstArg - First argument of a parser argument tree 737 * 738 * RETURN: Status 739 * 740 * DESCRIPTION: Convert an operator's arguments from a parse tree format to 741 * namespace objects and place those argument object on the object 742 * stack in preparation for evaluation by the interpreter. 743 * 744 ******************************************************************************/ 745 746 ACPI_STATUS 747 AcpiDsCreateOperands ( 748 ACPI_WALK_STATE *WalkState, 749 ACPI_PARSE_OBJECT *FirstArg) 750 { 751 ACPI_STATUS Status = AE_OK; 752 ACPI_PARSE_OBJECT *Arg; 753 ACPI_PARSE_OBJECT *Arguments[ACPI_OBJ_NUM_OPERANDS]; 754 UINT32 ArgCount = 0; 755 UINT32 Index = WalkState->NumOperands; 756 UINT32 i; 757 758 759 ACPI_FUNCTION_TRACE_PTR (DsCreateOperands, FirstArg); 760 761 762 /* Get all arguments in the list */ 763 764 Arg = FirstArg; 765 while (Arg) 766 { 767 if (Index >= ACPI_OBJ_NUM_OPERANDS) 768 { 769 return_ACPI_STATUS (AE_BAD_DATA); 770 } 771 772 Arguments[Index] = Arg; 773 WalkState->Operands [Index] = NULL; 774 775 /* Move on to next argument, if any */ 776 777 Arg = Arg->Common.Next; 778 ArgCount++; 779 Index++; 780 } 781 782 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 783 "NumOperands %d, ArgCount %d, Index %d\n", 784 WalkState->NumOperands, ArgCount, Index)); 785 786 /* Create the interpreter arguments, in reverse order */ 787 788 Index--; 789 for (i = 0; i < ArgCount; i++) 790 { 791 Arg = Arguments[Index]; 792 WalkState->OperandIndex = (UINT8) Index; 793 794 Status = AcpiDsCreateOperand (WalkState, Arg, Index); 795 if (ACPI_FAILURE (Status)) 796 { 797 goto Cleanup; 798 } 799 800 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 801 "Created Arg #%u (%p) %u args total\n", 802 Index, Arg, ArgCount)); 803 Index--; 804 } 805 806 return_ACPI_STATUS (Status); 807 808 809 Cleanup: 810 /* 811 * We must undo everything done above; meaning that we must 812 * pop everything off of the operand stack and delete those 813 * objects 814 */ 815 AcpiDsObjStackPopAndDelete (ArgCount, WalkState); 816 817 ACPI_EXCEPTION ((AE_INFO, Status, "While creating Arg %u", Index)); 818 return_ACPI_STATUS (Status); 819 } 820 821 822 /***************************************************************************** 823 * 824 * FUNCTION: AcpiDsEvaluateNamePath 825 * 826 * PARAMETERS: WalkState - Current state of the parse tree walk, 827 * the opcode of current operation should be 828 * AML_INT_NAMEPATH_OP 829 * 830 * RETURN: Status 831 * 832 * DESCRIPTION: Translate the -NamePath- parse tree object to the equivalent 833 * interpreter object, convert it to value, if needed, duplicate 834 * it, if needed, and push it onto the current result stack. 835 * 836 ****************************************************************************/ 837 838 ACPI_STATUS 839 AcpiDsEvaluateNamePath ( 840 ACPI_WALK_STATE *WalkState) 841 { 842 ACPI_STATUS Status = AE_OK; 843 ACPI_PARSE_OBJECT *Op = WalkState->Op; 844 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 845 ACPI_OPERAND_OBJECT *NewObjDesc; 846 UINT8 Type; 847 848 849 ACPI_FUNCTION_TRACE_PTR (DsEvaluateNamePath, WalkState); 850 851 852 if (!Op->Common.Parent) 853 { 854 /* This happens after certain exception processing */ 855 856 goto Exit; 857 } 858 859 if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || 860 (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP) || 861 (Op->Common.Parent->Common.AmlOpcode == AML_REF_OF_OP)) 862 { 863 /* TBD: Should we specify this feature as a bit of OpInfo->Flags of these opcodes? */ 864 865 goto Exit; 866 } 867 868 Status = AcpiDsCreateOperand (WalkState, Op, 0); 869 if (ACPI_FAILURE (Status)) 870 { 871 goto Exit; 872 } 873 874 if (Op->Common.Flags & ACPI_PARSEOP_TARGET) 875 { 876 NewObjDesc = *Operand; 877 goto PushResult; 878 } 879 880 Type = (*Operand)->Common.Type; 881 882 Status = AcpiExResolveToValue (Operand, WalkState); 883 if (ACPI_FAILURE (Status)) 884 { 885 goto Exit; 886 } 887 888 if (Type == ACPI_TYPE_INTEGER) 889 { 890 /* It was incremented by AcpiExResolveToValue */ 891 892 AcpiUtRemoveReference (*Operand); 893 894 Status = AcpiUtCopyIobjectToIobject (*Operand, &NewObjDesc, WalkState); 895 if (ACPI_FAILURE (Status)) 896 { 897 goto Exit; 898 } 899 } 900 else 901 { 902 /* 903 * The object either was anew created or is 904 * a Namespace node - don't decrement it. 905 */ 906 NewObjDesc = *Operand; 907 } 908 909 /* Cleanup for name-path operand */ 910 911 Status = AcpiDsObjStackPop (1, WalkState); 912 if (ACPI_FAILURE (Status)) 913 { 914 WalkState->ResultObj = NewObjDesc; 915 goto Exit; 916 } 917 918 PushResult: 919 920 WalkState->ResultObj = NewObjDesc; 921 922 Status = AcpiDsResultPush (WalkState->ResultObj, WalkState); 923 if (ACPI_SUCCESS (Status)) 924 { 925 /* Force to take it from stack */ 926 927 Op->Common.Flags |= ACPI_PARSEOP_IN_STACK; 928 } 929 930 Exit: 931 932 return_ACPI_STATUS (Status); 933 } 934