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