1 /******************************************************************************* 2 * 3 * Module Name: dsutils - Dispatcher utilities 4 * 5 ******************************************************************************/ 6 7 /****************************************************************************** 8 * 9 * 1. Copyright Notice 10 * 11 * Some or all of this work - Copyright (c) 1999 - 2013, Intel Corp. 12 * All rights reserved. 13 * 14 * 2. License 15 * 16 * 2.1. This is your license from Intel Corp. under its intellectual property 17 * rights. You may have additional license terms from the party that provided 18 * you this software, covering your right to use that party's intellectual 19 * property rights. 20 * 21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 22 * copy of the source code appearing in this file ("Covered Code") an 23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 24 * base code distributed originally by Intel ("Original Intel Code") to copy, 25 * make derivatives, distribute, use and display any portion of the Covered 26 * Code in any form, with the right to sublicense such rights; and 27 * 28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 29 * license (with the right to sublicense), under only those claims of Intel 30 * patents that are infringed by the Original Intel Code, to make, use, sell, 31 * offer to sell, and import the Covered Code and derivative works thereof 32 * solely to the minimum extent necessary to exercise the above copyright 33 * license, and in no event shall the patent license extend to any additions 34 * to or modifications of the Original Intel Code. No other license or right 35 * is granted directly or by implication, estoppel or otherwise; 36 * 37 * The above copyright and patent license is granted only if the following 38 * conditions are met: 39 * 40 * 3. Conditions 41 * 42 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 43 * Redistribution of source code of any substantial portion of the Covered 44 * Code or modification with rights to further distribute source must include 45 * the above Copyright Notice, the above License, this list of Conditions, 46 * and the following Disclaimer and Export Compliance provision. In addition, 47 * Licensee must cause all Covered Code to which Licensee contributes to 48 * contain a file documenting the changes Licensee made to create that Covered 49 * Code and the date of any change. Licensee must include in that file the 50 * documentation of any changes made by any predecessor Licensee. Licensee 51 * must include a prominent statement that the modification is derived, 52 * directly or indirectly, from Original Intel Code. 53 * 54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 55 * Redistribution of source code of any substantial portion of the Covered 56 * Code or modification without rights to further distribute source must 57 * include the following Disclaimer and Export Compliance provision in the 58 * documentation and/or other materials provided with distribution. In 59 * addition, Licensee may not authorize further sublicense of source of any 60 * portion of the Covered Code, and must include terms to the effect that the 61 * license from Licensee to its licensee is limited to the intellectual 62 * property embodied in the software Licensee provides to its licensee, and 63 * not to intellectual property embodied in modifications its licensee may 64 * make. 65 * 66 * 3.3. Redistribution of Executable. Redistribution in executable form of any 67 * substantial portion of the Covered Code or modification must reproduce the 68 * above Copyright Notice, and the following Disclaimer and Export Compliance 69 * provision in the documentation and/or other materials provided with the 70 * distribution. 71 * 72 * 3.4. Intel retains all right, title, and interest in and to the Original 73 * Intel Code. 74 * 75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 76 * Intel shall be used in advertising or otherwise to promote the sale, use or 77 * other dealings in products derived from or relating to the Covered Code 78 * without prior written authorization from Intel. 79 * 80 * 4. Disclaimer and Export Compliance 81 * 82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 88 * PARTICULAR PURPOSE. 89 * 90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 97 * LIMITED REMEDY. 98 * 99 * 4.3. Licensee shall not export, either directly or indirectly, any of this 100 * software or system incorporating such software without first obtaining any 101 * required license or other approval from the U. S. Department of Commerce or 102 * any other agency or department of the United States Government. In the 103 * event Licensee exports any such software from the United States or 104 * re-exports any such software from a foreign destination, Licensee shall 105 * ensure that the distribution and export/re-export of the software is in 106 * compliance with all laws, regulations, orders, or other restrictions of the 107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 108 * any of its subsidiaries will export/re-export any technical data, process, 109 * software, or service, directly or indirectly, to any country for which the 110 * United States government or any agency thereof requires an export license, 111 * other governmental approval, or letter of assurance, without first obtaining 112 * such license, approval or letter. 113 * 114 *****************************************************************************/ 115 116 #define __DSUTILS_C__ 117 118 #include "acpi.h" 119 #include "accommon.h" 120 #include "acparser.h" 121 #include "amlcode.h" 122 #include "acdispat.h" 123 #include "acinterp.h" 124 #include "acnamesp.h" 125 #include "acdebug.h" 126 127 #define _COMPONENT ACPI_DISPATCHER 128 ACPI_MODULE_NAME ("dsutils") 129 130 131 /******************************************************************************* 132 * 133 * FUNCTION: AcpiDsClearImplicitReturn 134 * 135 * PARAMETERS: WalkState - Current State 136 * 137 * RETURN: None. 138 * 139 * DESCRIPTION: Clear and remove a reference on an implicit return value. Used 140 * to delete "stale" return values (if enabled, the return value 141 * from every operator is saved at least momentarily, in case the 142 * parent method exits.) 143 * 144 ******************************************************************************/ 145 146 void 147 AcpiDsClearImplicitReturn ( 148 ACPI_WALK_STATE *WalkState) 149 { 150 ACPI_FUNCTION_NAME (DsClearImplicitReturn); 151 152 153 /* 154 * Slack must be enabled for this feature 155 */ 156 if (!AcpiGbl_EnableInterpreterSlack) 157 { 158 return; 159 } 160 161 if (WalkState->ImplicitReturnObj) 162 { 163 /* 164 * Delete any "stale" implicit return. However, in 165 * complex statements, the implicit return value can be 166 * bubbled up several levels. 167 */ 168 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 169 "Removing reference on stale implicit return obj %p\n", 170 WalkState->ImplicitReturnObj)); 171 172 AcpiUtRemoveReference (WalkState->ImplicitReturnObj); 173 WalkState->ImplicitReturnObj = NULL; 174 } 175 } 176 177 178 #ifndef ACPI_NO_METHOD_EXECUTION 179 /******************************************************************************* 180 * 181 * FUNCTION: AcpiDsDoImplicitReturn 182 * 183 * PARAMETERS: ReturnDesc - The return value 184 * WalkState - Current State 185 * AddReference - True if a reference should be added to the 186 * return object 187 * 188 * RETURN: TRUE if implicit return enabled, FALSE otherwise 189 * 190 * DESCRIPTION: Implements the optional "implicit return". We save the result 191 * of every ASL operator and control method invocation in case the 192 * parent method exit. Before storing a new return value, we 193 * delete the previous return value. 194 * 195 ******************************************************************************/ 196 197 BOOLEAN 198 AcpiDsDoImplicitReturn ( 199 ACPI_OPERAND_OBJECT *ReturnDesc, 200 ACPI_WALK_STATE *WalkState, 201 BOOLEAN AddReference) 202 { 203 ACPI_FUNCTION_NAME (DsDoImplicitReturn); 204 205 206 /* 207 * Slack must be enabled for this feature, and we must 208 * have a valid return object 209 */ 210 if ((!AcpiGbl_EnableInterpreterSlack) || 211 (!ReturnDesc)) 212 { 213 return (FALSE); 214 } 215 216 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 217 "Result %p will be implicitly returned; Prev=%p\n", 218 ReturnDesc, 219 WalkState->ImplicitReturnObj)); 220 221 /* 222 * Delete any "stale" implicit return value first. However, in 223 * complex statements, the implicit return value can be 224 * bubbled up several levels, so we don't clear the value if it 225 * is the same as the ReturnDesc. 226 */ 227 if (WalkState->ImplicitReturnObj) 228 { 229 if (WalkState->ImplicitReturnObj == ReturnDesc) 230 { 231 return (TRUE); 232 } 233 AcpiDsClearImplicitReturn (WalkState); 234 } 235 236 /* Save the implicit return value, add a reference if requested */ 237 238 WalkState->ImplicitReturnObj = ReturnDesc; 239 if (AddReference) 240 { 241 AcpiUtAddReference (ReturnDesc); 242 } 243 244 return (TRUE); 245 } 246 247 248 /******************************************************************************* 249 * 250 * FUNCTION: AcpiDsIsResultUsed 251 * 252 * PARAMETERS: Op - Current Op 253 * WalkState - Current State 254 * 255 * RETURN: TRUE if result is used, FALSE otherwise 256 * 257 * DESCRIPTION: Check if a result object will be used by the parent 258 * 259 ******************************************************************************/ 260 261 BOOLEAN 262 AcpiDsIsResultUsed ( 263 ACPI_PARSE_OBJECT *Op, 264 ACPI_WALK_STATE *WalkState) 265 { 266 const ACPI_OPCODE_INFO *ParentInfo; 267 268 ACPI_FUNCTION_TRACE_PTR (DsIsResultUsed, Op); 269 270 271 /* Must have both an Op and a Result Object */ 272 273 if (!Op) 274 { 275 ACPI_ERROR ((AE_INFO, "Null Op")); 276 return_UINT8 (TRUE); 277 } 278 279 /* 280 * We know that this operator is not a 281 * Return() operator (would not come here.) The following code is the 282 * optional support for a so-called "implicit return". Some AML code 283 * assumes that the last value of the method is "implicitly" returned 284 * to the caller. Just save the last result as the return value. 285 * NOTE: this is optional because the ASL language does not actually 286 * support this behavior. 287 */ 288 (void) AcpiDsDoImplicitReturn (WalkState->ResultObj, WalkState, TRUE); 289 290 /* 291 * Now determine if the parent will use the result 292 * 293 * If there is no parent, or the parent is a ScopeOp, we are executing 294 * at the method level. An executing method typically has no parent, 295 * since each method is parsed separately. A method invoked externally 296 * via ExecuteControlMethod has a ScopeOp as the parent. 297 */ 298 if ((!Op->Common.Parent) || 299 (Op->Common.Parent->Common.AmlOpcode == AML_SCOPE_OP)) 300 { 301 /* No parent, the return value cannot possibly be used */ 302 303 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 304 "At Method level, result of [%s] not used\n", 305 AcpiPsGetOpcodeName (Op->Common.AmlOpcode))); 306 return_UINT8 (FALSE); 307 } 308 309 /* Get info on the parent. The RootOp is AML_SCOPE */ 310 311 ParentInfo = AcpiPsGetOpcodeInfo (Op->Common.Parent->Common.AmlOpcode); 312 if (ParentInfo->Class == AML_CLASS_UNKNOWN) 313 { 314 ACPI_ERROR ((AE_INFO, 315 "Unknown parent opcode Op=%p", Op)); 316 return_UINT8 (FALSE); 317 } 318 319 /* 320 * Decide what to do with the result based on the parent. If 321 * the parent opcode will not use the result, delete the object. 322 * Otherwise leave it as is, it will be deleted when it is used 323 * as an operand later. 324 */ 325 switch (ParentInfo->Class) 326 { 327 case AML_CLASS_CONTROL: 328 329 switch (Op->Common.Parent->Common.AmlOpcode) 330 { 331 case AML_RETURN_OP: 332 333 /* Never delete the return value associated with a return opcode */ 334 335 goto ResultUsed; 336 337 case AML_IF_OP: 338 case AML_WHILE_OP: 339 /* 340 * If we are executing the predicate AND this is the predicate op, 341 * we will use the return value 342 */ 343 if ((WalkState->ControlState->Common.State == ACPI_CONTROL_PREDICATE_EXECUTING) && 344 (WalkState->ControlState->Control.PredicateOp == Op)) 345 { 346 goto ResultUsed; 347 } 348 break; 349 350 default: 351 352 /* Ignore other control opcodes */ 353 354 break; 355 } 356 357 /* The general control opcode returns no result */ 358 359 goto ResultNotUsed; 360 361 case AML_CLASS_CREATE: 362 /* 363 * These opcodes allow TermArg(s) as operands and therefore 364 * the operands can be method calls. The result is used. 365 */ 366 goto ResultUsed; 367 368 case AML_CLASS_NAMED_OBJECT: 369 370 if ((Op->Common.Parent->Common.AmlOpcode == AML_REGION_OP) || 371 (Op->Common.Parent->Common.AmlOpcode == AML_DATA_REGION_OP) || 372 (Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || 373 (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP) || 374 (Op->Common.Parent->Common.AmlOpcode == AML_BUFFER_OP) || 375 (Op->Common.Parent->Common.AmlOpcode == AML_INT_EVAL_SUBTREE_OP) || 376 (Op->Common.Parent->Common.AmlOpcode == AML_BANK_FIELD_OP)) 377 { 378 /* 379 * These opcodes allow TermArg(s) as operands and therefore 380 * the operands can be method calls. The result is used. 381 */ 382 goto ResultUsed; 383 } 384 385 goto ResultNotUsed; 386 387 default: 388 /* 389 * In all other cases. the parent will actually use the return 390 * object, so keep it. 391 */ 392 goto ResultUsed; 393 } 394 395 396 ResultUsed: 397 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 398 "Result of [%s] used by Parent [%s] Op=%p\n", 399 AcpiPsGetOpcodeName (Op->Common.AmlOpcode), 400 AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op)); 401 402 return_UINT8 (TRUE); 403 404 405 ResultNotUsed: 406 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 407 "Result of [%s] not used by Parent [%s] Op=%p\n", 408 AcpiPsGetOpcodeName (Op->Common.AmlOpcode), 409 AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op)); 410 411 return_UINT8 (FALSE); 412 } 413 414 415 /******************************************************************************* 416 * 417 * FUNCTION: AcpiDsDeleteResultIfNotUsed 418 * 419 * PARAMETERS: Op - Current parse Op 420 * ResultObj - Result of the operation 421 * WalkState - Current state 422 * 423 * RETURN: Status 424 * 425 * DESCRIPTION: Used after interpretation of an opcode. If there is an internal 426 * result descriptor, check if the parent opcode will actually use 427 * this result. If not, delete the result now so that it will 428 * not become orphaned. 429 * 430 ******************************************************************************/ 431 432 void 433 AcpiDsDeleteResultIfNotUsed ( 434 ACPI_PARSE_OBJECT *Op, 435 ACPI_OPERAND_OBJECT *ResultObj, 436 ACPI_WALK_STATE *WalkState) 437 { 438 ACPI_OPERAND_OBJECT *ObjDesc; 439 ACPI_STATUS Status; 440 441 442 ACPI_FUNCTION_TRACE_PTR (DsDeleteResultIfNotUsed, ResultObj); 443 444 445 if (!Op) 446 { 447 ACPI_ERROR ((AE_INFO, "Null Op")); 448 return_VOID; 449 } 450 451 if (!ResultObj) 452 { 453 return_VOID; 454 } 455 456 if (!AcpiDsIsResultUsed (Op, WalkState)) 457 { 458 /* Must pop the result stack (ObjDesc should be equal to ResultObj) */ 459 460 Status = AcpiDsResultPop (&ObjDesc, WalkState); 461 if (ACPI_SUCCESS (Status)) 462 { 463 AcpiUtRemoveReference (ResultObj); 464 } 465 } 466 467 return_VOID; 468 } 469 470 471 /******************************************************************************* 472 * 473 * FUNCTION: AcpiDsResolveOperands 474 * 475 * PARAMETERS: WalkState - Current walk state with operands on stack 476 * 477 * RETURN: Status 478 * 479 * DESCRIPTION: Resolve all operands to their values. Used to prepare 480 * arguments to a control method invocation (a call from one 481 * method to another.) 482 * 483 ******************************************************************************/ 484 485 ACPI_STATUS 486 AcpiDsResolveOperands ( 487 ACPI_WALK_STATE *WalkState) 488 { 489 UINT32 i; 490 ACPI_STATUS Status = AE_OK; 491 492 493 ACPI_FUNCTION_TRACE_PTR (DsResolveOperands, WalkState); 494 495 496 /* 497 * Attempt to resolve each of the valid operands 498 * Method arguments are passed by reference, not by value. This means 499 * that the actual objects are passed, not copies of the objects. 500 */ 501 for (i = 0; i < WalkState->NumOperands; i++) 502 { 503 Status = AcpiExResolveToValue (&WalkState->Operands[i], WalkState); 504 if (ACPI_FAILURE (Status)) 505 { 506 break; 507 } 508 } 509 510 return_ACPI_STATUS (Status); 511 } 512 513 514 /******************************************************************************* 515 * 516 * FUNCTION: AcpiDsClearOperands 517 * 518 * PARAMETERS: WalkState - Current walk state with operands on stack 519 * 520 * RETURN: None 521 * 522 * DESCRIPTION: Clear all operands on the current walk state operand stack. 523 * 524 ******************************************************************************/ 525 526 void 527 AcpiDsClearOperands ( 528 ACPI_WALK_STATE *WalkState) 529 { 530 UINT32 i; 531 532 533 ACPI_FUNCTION_TRACE_PTR (DsClearOperands, WalkState); 534 535 536 /* Remove a reference on each operand on the stack */ 537 538 for (i = 0; i < WalkState->NumOperands; i++) 539 { 540 /* 541 * Remove a reference to all operands, including both 542 * "Arguments" and "Targets". 543 */ 544 AcpiUtRemoveReference (WalkState->Operands[i]); 545 WalkState->Operands[i] = NULL; 546 } 547 548 WalkState->NumOperands = 0; 549 return_VOID; 550 } 551 #endif 552 553 554 /******************************************************************************* 555 * 556 * FUNCTION: AcpiDsCreateOperand 557 * 558 * PARAMETERS: WalkState - Current walk state 559 * Arg - Parse object for the argument 560 * ArgIndex - Which argument (zero based) 561 * 562 * RETURN: Status 563 * 564 * DESCRIPTION: Translate a parse tree object that is an argument to an AML 565 * opcode to the equivalent interpreter object. This may include 566 * looking up a name or entering a new name into the internal 567 * namespace. 568 * 569 ******************************************************************************/ 570 571 ACPI_STATUS 572 AcpiDsCreateOperand ( 573 ACPI_WALK_STATE *WalkState, 574 ACPI_PARSE_OBJECT *Arg, 575 UINT32 ArgIndex) 576 { 577 ACPI_STATUS Status = AE_OK; 578 char *NameString; 579 UINT32 NameLength; 580 ACPI_OPERAND_OBJECT *ObjDesc; 581 ACPI_PARSE_OBJECT *ParentOp; 582 UINT16 Opcode; 583 ACPI_INTERPRETER_MODE InterpreterMode; 584 const ACPI_OPCODE_INFO *OpInfo; 585 586 587 ACPI_FUNCTION_TRACE_PTR (DsCreateOperand, Arg); 588 589 590 /* A valid name must be looked up in the namespace */ 591 592 if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && 593 (Arg->Common.Value.String) && 594 !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK)) 595 { 596 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", Arg)); 597 598 /* Get the entire name string from the AML stream */ 599 600 Status = AcpiExGetNameString (ACPI_TYPE_ANY, Arg->Common.Value.Buffer, 601 &NameString, &NameLength); 602 603 if (ACPI_FAILURE (Status)) 604 { 605 return_ACPI_STATUS (Status); 606 } 607 608 /* All prefixes have been handled, and the name is in NameString */ 609 610 /* 611 * Special handling for BufferField declarations. This is a deferred 612 * opcode that unfortunately defines the field name as the last 613 * parameter instead of the first. We get here when we are performing 614 * the deferred execution, so the actual name of the field is already 615 * in the namespace. We don't want to attempt to look it up again 616 * because we may be executing in a different scope than where the 617 * actual opcode exists. 618 */ 619 if ((WalkState->DeferredNode) && 620 (WalkState->DeferredNode->Type == ACPI_TYPE_BUFFER_FIELD) && 621 (ArgIndex == (UINT32) ((WalkState->Opcode == AML_CREATE_FIELD_OP) ? 3 : 2))) 622 { 623 ObjDesc = ACPI_CAST_PTR ( 624 ACPI_OPERAND_OBJECT, WalkState->DeferredNode); 625 Status = AE_OK; 626 } 627 else /* All other opcodes */ 628 { 629 /* 630 * Differentiate between a namespace "create" operation 631 * versus a "lookup" operation (IMODE_LOAD_PASS2 vs. 632 * IMODE_EXECUTE) in order to support the creation of 633 * namespace objects during the execution of control methods. 634 */ 635 ParentOp = Arg->Common.Parent; 636 OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode); 637 if ((OpInfo->Flags & AML_NSNODE) && 638 (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) && 639 (ParentOp->Common.AmlOpcode != AML_REGION_OP) && 640 (ParentOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP)) 641 { 642 /* Enter name into namespace if not found */ 643 644 InterpreterMode = ACPI_IMODE_LOAD_PASS2; 645 } 646 else 647 { 648 /* Return a failure if name not found */ 649 650 InterpreterMode = ACPI_IMODE_EXECUTE; 651 } 652 653 Status = AcpiNsLookup (WalkState->ScopeInfo, NameString, 654 ACPI_TYPE_ANY, InterpreterMode, 655 ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, 656 WalkState, 657 ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &ObjDesc)); 658 /* 659 * The only case where we pass through (ignore) a NOT_FOUND 660 * error is for the CondRefOf opcode. 661 */ 662 if (Status == AE_NOT_FOUND) 663 { 664 if (ParentOp->Common.AmlOpcode == AML_COND_REF_OF_OP) 665 { 666 /* 667 * For the Conditional Reference op, it's OK if 668 * the name is not found; We just need a way to 669 * indicate this to the interpreter, set the 670 * object to the root 671 */ 672 ObjDesc = ACPI_CAST_PTR ( 673 ACPI_OPERAND_OBJECT, AcpiGbl_RootNode); 674 Status = AE_OK; 675 } 676 else 677 { 678 /* 679 * We just plain didn't find it -- which is a 680 * very serious error at this point 681 */ 682 Status = AE_AML_NAME_NOT_FOUND; 683 } 684 } 685 686 if (ACPI_FAILURE (Status)) 687 { 688 ACPI_ERROR_NAMESPACE (NameString, Status); 689 } 690 } 691 692 /* Free the namestring created above */ 693 694 ACPI_FREE (NameString); 695 696 /* Check status from the lookup */ 697 698 if (ACPI_FAILURE (Status)) 699 { 700 return_ACPI_STATUS (Status); 701 } 702 703 /* Put the resulting object onto the current object stack */ 704 705 Status = AcpiDsObjStackPush (ObjDesc, WalkState); 706 if (ACPI_FAILURE (Status)) 707 { 708 return_ACPI_STATUS (Status); 709 } 710 ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState)); 711 } 712 else 713 { 714 /* Check for null name case */ 715 716 if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && 717 !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK)) 718 { 719 /* 720 * If the name is null, this means that this is an 721 * optional result parameter that was not specified 722 * in the original ASL. Create a Zero Constant for a 723 * placeholder. (Store to a constant is a Noop.) 724 */ 725 Opcode = AML_ZERO_OP; /* Has no arguments! */ 726 727 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 728 "Null namepath: Arg=%p\n", Arg)); 729 } 730 else 731 { 732 Opcode = Arg->Common.AmlOpcode; 733 } 734 735 /* Get the object type of the argument */ 736 737 OpInfo = AcpiPsGetOpcodeInfo (Opcode); 738 if (OpInfo->ObjectType == ACPI_TYPE_INVALID) 739 { 740 return_ACPI_STATUS (AE_NOT_IMPLEMENTED); 741 } 742 743 if ((OpInfo->Flags & AML_HAS_RETVAL) || (Arg->Common.Flags & ACPI_PARSEOP_IN_STACK)) 744 { 745 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 746 "Argument previously created, already stacked\n")); 747 748 ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject ( 749 WalkState->Operands [WalkState->NumOperands - 1], WalkState)); 750 751 /* 752 * Use value that was already previously returned 753 * by the evaluation of this argument 754 */ 755 Status = AcpiDsResultPop (&ObjDesc, WalkState); 756 if (ACPI_FAILURE (Status)) 757 { 758 /* 759 * Only error is underflow, and this indicates 760 * a missing or null operand! 761 */ 762 ACPI_EXCEPTION ((AE_INFO, Status, 763 "Missing or null operand")); 764 return_ACPI_STATUS (Status); 765 } 766 } 767 else 768 { 769 /* Create an ACPI_INTERNAL_OBJECT for the argument */ 770 771 ObjDesc = AcpiUtCreateInternalObject (OpInfo->ObjectType); 772 if (!ObjDesc) 773 { 774 return_ACPI_STATUS (AE_NO_MEMORY); 775 } 776 777 /* Initialize the new object */ 778 779 Status = AcpiDsInitObjectFromOp ( 780 WalkState, Arg, Opcode, &ObjDesc); 781 if (ACPI_FAILURE (Status)) 782 { 783 AcpiUtDeleteObjectDesc (ObjDesc); 784 return_ACPI_STATUS (Status); 785 } 786 } 787 788 /* Put the operand object on the object stack */ 789 790 Status = AcpiDsObjStackPush (ObjDesc, WalkState); 791 if (ACPI_FAILURE (Status)) 792 { 793 return_ACPI_STATUS (Status); 794 } 795 796 ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState)); 797 } 798 799 return_ACPI_STATUS (AE_OK); 800 } 801 802 803 /******************************************************************************* 804 * 805 * FUNCTION: AcpiDsCreateOperands 806 * 807 * PARAMETERS: WalkState - Current state 808 * FirstArg - First argument of a parser argument tree 809 * 810 * RETURN: Status 811 * 812 * DESCRIPTION: Convert an operator's arguments from a parse tree format to 813 * namespace objects and place those argument object on the object 814 * stack in preparation for evaluation by the interpreter. 815 * 816 ******************************************************************************/ 817 818 ACPI_STATUS 819 AcpiDsCreateOperands ( 820 ACPI_WALK_STATE *WalkState, 821 ACPI_PARSE_OBJECT *FirstArg) 822 { 823 ACPI_STATUS Status = AE_OK; 824 ACPI_PARSE_OBJECT *Arg; 825 ACPI_PARSE_OBJECT *Arguments[ACPI_OBJ_NUM_OPERANDS]; 826 UINT32 ArgCount = 0; 827 UINT32 Index = WalkState->NumOperands; 828 UINT32 i; 829 830 831 ACPI_FUNCTION_TRACE_PTR (DsCreateOperands, FirstArg); 832 833 834 /* Get all arguments in the list */ 835 836 Arg = FirstArg; 837 while (Arg) 838 { 839 if (Index >= ACPI_OBJ_NUM_OPERANDS) 840 { 841 return_ACPI_STATUS (AE_BAD_DATA); 842 } 843 844 Arguments[Index] = Arg; 845 WalkState->Operands [Index] = NULL; 846 847 /* Move on to next argument, if any */ 848 849 Arg = Arg->Common.Next; 850 ArgCount++; 851 Index++; 852 } 853 854 Index--; 855 856 /* It is the appropriate order to get objects from the Result stack */ 857 858 for (i = 0; i < ArgCount; i++) 859 { 860 Arg = Arguments[Index]; 861 862 /* Force the filling of the operand stack in inverse order */ 863 864 WalkState->OperandIndex = (UINT8) Index; 865 866 Status = AcpiDsCreateOperand (WalkState, Arg, Index); 867 if (ACPI_FAILURE (Status)) 868 { 869 goto Cleanup; 870 } 871 872 Index--; 873 874 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Arg #%u (%p) done, Arg1=%p\n", 875 Index, Arg, FirstArg)); 876 } 877 878 return_ACPI_STATUS (Status); 879 880 881 Cleanup: 882 /* 883 * We must undo everything done above; meaning that we must 884 * pop everything off of the operand stack and delete those 885 * objects 886 */ 887 AcpiDsObjStackPopAndDelete (ArgCount, WalkState); 888 889 ACPI_EXCEPTION ((AE_INFO, Status, "While creating Arg %u", Index)); 890 return_ACPI_STATUS (Status); 891 } 892 893 894 /***************************************************************************** 895 * 896 * FUNCTION: AcpiDsEvaluateNamePath 897 * 898 * PARAMETERS: WalkState - Current state of the parse tree walk, 899 * the opcode of current operation should be 900 * AML_INT_NAMEPATH_OP 901 * 902 * RETURN: Status 903 * 904 * DESCRIPTION: Translate the -NamePath- parse tree object to the equivalent 905 * interpreter object, convert it to value, if needed, duplicate 906 * it, if needed, and push it onto the current result stack. 907 * 908 ****************************************************************************/ 909 910 ACPI_STATUS 911 AcpiDsEvaluateNamePath ( 912 ACPI_WALK_STATE *WalkState) 913 { 914 ACPI_STATUS Status = AE_OK; 915 ACPI_PARSE_OBJECT *Op = WalkState->Op; 916 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 917 ACPI_OPERAND_OBJECT *NewObjDesc; 918 UINT8 Type; 919 920 921 ACPI_FUNCTION_TRACE_PTR (DsEvaluateNamePath, WalkState); 922 923 924 if (!Op->Common.Parent) 925 { 926 /* This happens after certain exception processing */ 927 928 goto Exit; 929 } 930 931 if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || 932 (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP) || 933 (Op->Common.Parent->Common.AmlOpcode == AML_REF_OF_OP)) 934 { 935 /* TBD: Should we specify this feature as a bit of OpInfo->Flags of these opcodes? */ 936 937 goto Exit; 938 } 939 940 Status = AcpiDsCreateOperand (WalkState, Op, 0); 941 if (ACPI_FAILURE (Status)) 942 { 943 goto Exit; 944 } 945 946 if (Op->Common.Flags & ACPI_PARSEOP_TARGET) 947 { 948 NewObjDesc = *Operand; 949 goto PushResult; 950 } 951 952 Type = (*Operand)->Common.Type; 953 954 Status = AcpiExResolveToValue (Operand, WalkState); 955 if (ACPI_FAILURE (Status)) 956 { 957 goto Exit; 958 } 959 960 if (Type == ACPI_TYPE_INTEGER) 961 { 962 /* It was incremented by AcpiExResolveToValue */ 963 964 AcpiUtRemoveReference (*Operand); 965 966 Status = AcpiUtCopyIobjectToIobject (*Operand, &NewObjDesc, WalkState); 967 if (ACPI_FAILURE (Status)) 968 { 969 goto Exit; 970 } 971 } 972 else 973 { 974 /* 975 * The object either was anew created or is 976 * a Namespace node - don't decrement it. 977 */ 978 NewObjDesc = *Operand; 979 } 980 981 /* Cleanup for name-path operand */ 982 983 Status = AcpiDsObjStackPop (1, WalkState); 984 if (ACPI_FAILURE (Status)) 985 { 986 WalkState->ResultObj = NewObjDesc; 987 goto Exit; 988 } 989 990 PushResult: 991 992 WalkState->ResultObj = NewObjDesc; 993 994 Status = AcpiDsResultPush (WalkState->ResultObj, WalkState); 995 if (ACPI_SUCCESS (Status)) 996 { 997 /* Force to take it from stack */ 998 999 Op->Common.Flags |= ACPI_PARSEOP_IN_STACK; 1000 } 1001 1002 Exit: 1003 1004 return_ACPI_STATUS (Status); 1005 } 1006