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