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