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