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