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