167754Smsmith/******************************************************************************* 267754Smsmith * 367754Smsmith * Module Name: dsutils - Dispatcher utilities 467754Smsmith * 567754Smsmith ******************************************************************************/ 667754Smsmith 7217365Sjkim/* 8281075Sdim * Copyright (C) 2000 - 2015, Intel Corp. 970243Smsmith * All rights reserved. 1067754Smsmith * 11217365Sjkim * Redistribution and use in source and binary forms, with or without 12217365Sjkim * modification, are permitted provided that the following conditions 13217365Sjkim * are met: 14217365Sjkim * 1. Redistributions of source code must retain the above copyright 15217365Sjkim * notice, this list of conditions, and the following disclaimer, 16217365Sjkim * without modification. 17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20217365Sjkim * including a substantially similar Disclaimer requirement for further 21217365Sjkim * binary redistribution. 22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23217365Sjkim * of any contributors may be used to endorse or promote products derived 24217365Sjkim * from this software without specific prior written permission. 2567754Smsmith * 26217365Sjkim * Alternatively, this software may be distributed under the terms of the 27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28217365Sjkim * Software Foundation. 2967754Smsmith * 30217365Sjkim * NO WARRANTY 31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 42217365Sjkim */ 4367754Smsmith 44193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 45193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 46193341Sjkim#include <contrib/dev/acpica/include/acparser.h> 47193341Sjkim#include <contrib/dev/acpica/include/amlcode.h> 48193341Sjkim#include <contrib/dev/acpica/include/acdispat.h> 49193341Sjkim#include <contrib/dev/acpica/include/acinterp.h> 50193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h> 51193341Sjkim#include <contrib/dev/acpica/include/acdebug.h> 5267754Smsmith 5377424Smsmith#define _COMPONENT ACPI_DISPATCHER 5491116Smsmith ACPI_MODULE_NAME ("dsutils") 5567754Smsmith 56123315Snjl 57151937Sjkim/******************************************************************************* 58151937Sjkim * 59151937Sjkim * FUNCTION: AcpiDsClearImplicitReturn 60151937Sjkim * 61151937Sjkim * PARAMETERS: WalkState - Current State 62151937Sjkim * 63151937Sjkim * RETURN: None. 64151937Sjkim * 65241973Sjkim * DESCRIPTION: Clear and remove a reference on an implicit return value. Used 66151937Sjkim * to delete "stale" return values (if enabled, the return value 67151937Sjkim * from every operator is saved at least momentarily, in case the 68151937Sjkim * parent method exits.) 69151937Sjkim * 70151937Sjkim ******************************************************************************/ 71151937Sjkim 72151937Sjkimvoid 73151937SjkimAcpiDsClearImplicitReturn ( 74151937Sjkim ACPI_WALK_STATE *WalkState) 75151937Sjkim{ 76167802Sjkim ACPI_FUNCTION_NAME (DsClearImplicitReturn); 77151937Sjkim 78151937Sjkim 79151937Sjkim /* 80151937Sjkim * Slack must be enabled for this feature 81151937Sjkim */ 82151937Sjkim if (!AcpiGbl_EnableInterpreterSlack) 83151937Sjkim { 84151937Sjkim return; 85151937Sjkim } 86151937Sjkim 87151937Sjkim if (WalkState->ImplicitReturnObj) 88151937Sjkim { 89151937Sjkim /* 90151937Sjkim * Delete any "stale" implicit return. However, in 91151937Sjkim * complex statements, the implicit return value can be 92151937Sjkim * bubbled up several levels. 93151937Sjkim */ 94151937Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 95151937Sjkim "Removing reference on stale implicit return obj %p\n", 96151937Sjkim WalkState->ImplicitReturnObj)); 97151937Sjkim 98151937Sjkim AcpiUtRemoveReference (WalkState->ImplicitReturnObj); 99151937Sjkim WalkState->ImplicitReturnObj = NULL; 100151937Sjkim } 101151937Sjkim} 102151937Sjkim 103151937Sjkim 104100966Siwasaki#ifndef ACPI_NO_METHOD_EXECUTION 105151937Sjkim/******************************************************************************* 106151937Sjkim * 107151937Sjkim * FUNCTION: AcpiDsDoImplicitReturn 108151937Sjkim * 109151937Sjkim * PARAMETERS: ReturnDesc - The return value 110151937Sjkim * WalkState - Current State 111151937Sjkim * AddReference - True if a reference should be added to the 112151937Sjkim * return object 113151937Sjkim * 114151937Sjkim * RETURN: TRUE if implicit return enabled, FALSE otherwise 115151937Sjkim * 116151937Sjkim * DESCRIPTION: Implements the optional "implicit return". We save the result 117151937Sjkim * of every ASL operator and control method invocation in case the 118241973Sjkim * parent method exit. Before storing a new return value, we 119151937Sjkim * delete the previous return value. 120151937Sjkim * 121151937Sjkim ******************************************************************************/ 12267754Smsmith 123151937SjkimBOOLEAN 124151937SjkimAcpiDsDoImplicitReturn ( 125151937Sjkim ACPI_OPERAND_OBJECT *ReturnDesc, 126151937Sjkim ACPI_WALK_STATE *WalkState, 127151937Sjkim BOOLEAN AddReference) 128151937Sjkim{ 129167802Sjkim ACPI_FUNCTION_NAME (DsDoImplicitReturn); 130151937Sjkim 131151937Sjkim 132151937Sjkim /* 133151937Sjkim * Slack must be enabled for this feature, and we must 134151937Sjkim * have a valid return object 135151937Sjkim */ 136151937Sjkim if ((!AcpiGbl_EnableInterpreterSlack) || 137151937Sjkim (!ReturnDesc)) 138151937Sjkim { 139151937Sjkim return (FALSE); 140151937Sjkim } 141151937Sjkim 142151937Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 143151937Sjkim "Result %p will be implicitly returned; Prev=%p\n", 144151937Sjkim ReturnDesc, 145151937Sjkim WalkState->ImplicitReturnObj)); 146151937Sjkim 147151937Sjkim /* 148151937Sjkim * Delete any "stale" implicit return value first. However, in 149151937Sjkim * complex statements, the implicit return value can be 150151937Sjkim * bubbled up several levels, so we don't clear the value if it 151151937Sjkim * is the same as the ReturnDesc. 152151937Sjkim */ 153151937Sjkim if (WalkState->ImplicitReturnObj) 154151937Sjkim { 155151937Sjkim if (WalkState->ImplicitReturnObj == ReturnDesc) 156151937Sjkim { 157151937Sjkim return (TRUE); 158151937Sjkim } 159151937Sjkim AcpiDsClearImplicitReturn (WalkState); 160151937Sjkim } 161151937Sjkim 162151937Sjkim /* Save the implicit return value, add a reference if requested */ 163151937Sjkim 164151937Sjkim WalkState->ImplicitReturnObj = ReturnDesc; 165151937Sjkim if (AddReference) 166151937Sjkim { 167151937Sjkim AcpiUtAddReference (ReturnDesc); 168151937Sjkim } 169151937Sjkim 170151937Sjkim return (TRUE); 171151937Sjkim} 172151937Sjkim 173151937Sjkim 17467754Smsmith/******************************************************************************* 17567754Smsmith * 17667754Smsmith * FUNCTION: AcpiDsIsResultUsed 17767754Smsmith * 178138287Smarks * PARAMETERS: Op - Current Op 179138287Smarks * WalkState - Current State 18067754Smsmith * 181138287Smarks * RETURN: TRUE if result is used, FALSE otherwise 18267754Smsmith * 18367754Smsmith * DESCRIPTION: Check if a result object will be used by the parent 18467754Smsmith * 18567754Smsmith ******************************************************************************/ 18667754Smsmith 18767754SmsmithBOOLEAN 18867754SmsmithAcpiDsIsResultUsed ( 18967754Smsmith ACPI_PARSE_OBJECT *Op, 19067754Smsmith ACPI_WALK_STATE *WalkState) 19167754Smsmith{ 19283174Smsmith const ACPI_OPCODE_INFO *ParentInfo; 19367754Smsmith 194167802Sjkim ACPI_FUNCTION_TRACE_PTR (DsIsResultUsed, Op); 19567754Smsmith 19667754Smsmith 19767754Smsmith /* Must have both an Op and a Result Object */ 19867754Smsmith 19967754Smsmith if (!Op) 20067754Smsmith { 201167802Sjkim ACPI_ERROR ((AE_INFO, "Null Op")); 202246849Sjkim return_UINT8 (TRUE); 20367754Smsmith } 20467754Smsmith 20567754Smsmith /* 206151937Sjkim * We know that this operator is not a 207151937Sjkim * Return() operator (would not come here.) The following code is the 208151937Sjkim * optional support for a so-called "implicit return". Some AML code 209151937Sjkim * assumes that the last value of the method is "implicitly" returned 210151937Sjkim * to the caller. Just save the last result as the return value. 211151937Sjkim * NOTE: this is optional because the ASL language does not actually 212151937Sjkim * support this behavior. 21367754Smsmith */ 214151937Sjkim (void) AcpiDsDoImplicitReturn (WalkState->ResultObj, WalkState, TRUE); 215151937Sjkim 216151937Sjkim /* 217151937Sjkim * Now determine if the parent will use the result 218151937Sjkim * 219151937Sjkim * If there is no parent, or the parent is a ScopeOp, we are executing 220151937Sjkim * at the method level. An executing method typically has no parent, 221241973Sjkim * since each method is parsed separately. A method invoked externally 222151937Sjkim * via ExecuteControlMethod has a ScopeOp as the parent. 223151937Sjkim */ 224151937Sjkim if ((!Op->Common.Parent) || 225151937Sjkim (Op->Common.Parent->Common.AmlOpcode == AML_SCOPE_OP)) 22667754Smsmith { 227138287Smarks /* No parent, the return value cannot possibly be used */ 228138287Smarks 229151937Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 230151937Sjkim "At Method level, result of [%s] not used\n", 231151937Sjkim AcpiPsGetOpcodeName (Op->Common.AmlOpcode))); 232246849Sjkim return_UINT8 (FALSE); 23367754Smsmith } 23467754Smsmith 235138287Smarks /* Get info on the parent. The RootOp is AML_SCOPE */ 236138287Smarks 23799679Siwasaki ParentInfo = AcpiPsGetOpcodeInfo (Op->Common.Parent->Common.AmlOpcode); 23885756Smsmith if (ParentInfo->Class == AML_CLASS_UNKNOWN) 23967754Smsmith { 240167802Sjkim ACPI_ERROR ((AE_INFO, 241167802Sjkim "Unknown parent opcode Op=%p", Op)); 242246849Sjkim return_UINT8 (FALSE); 24367754Smsmith } 24467754Smsmith 24567754Smsmith /* 246241973Sjkim * Decide what to do with the result based on the parent. If 24767754Smsmith * the parent opcode will not use the result, delete the object. 24867754Smsmith * Otherwise leave it as is, it will be deleted when it is used 24967754Smsmith * as an operand later. 25067754Smsmith */ 25185756Smsmith switch (ParentInfo->Class) 25267754Smsmith { 25387031Smsmith case AML_CLASS_CONTROL: 25467754Smsmith 25599679Siwasaki switch (Op->Common.Parent->Common.AmlOpcode) 25667754Smsmith { 25767754Smsmith case AML_RETURN_OP: 25867754Smsmith 25967754Smsmith /* Never delete the return value associated with a return opcode */ 26067754Smsmith 26187031Smsmith goto ResultUsed; 26267754Smsmith 26367754Smsmith case AML_IF_OP: 26467754Smsmith case AML_WHILE_OP: 26569450Smsmith /* 26669450Smsmith * If we are executing the predicate AND this is the predicate op, 26787031Smsmith * we will use the return value 26867754Smsmith */ 26991116Smsmith if ((WalkState->ControlState->Common.State == ACPI_CONTROL_PREDICATE_EXECUTING) && 27067754Smsmith (WalkState->ControlState->Control.PredicateOp == Op)) 27167754Smsmith { 27287031Smsmith goto ResultUsed; 27367754Smsmith } 27499679Siwasaki break; 27599679Siwasaki 27699679Siwasaki default: 277250838Sjkim 27899679Siwasaki /* Ignore other control opcodes */ 279250838Sjkim 28099679Siwasaki break; 28167754Smsmith } 28267754Smsmith 28387031Smsmith /* The general control opcode returns no result */ 28469450Smsmith 28587031Smsmith goto ResultNotUsed; 28667754Smsmith 28785756Smsmith case AML_CLASS_CREATE: 28870243Smsmith /* 28969746Smsmith * These opcodes allow TermArg(s) as operands and therefore 290241973Sjkim * the operands can be method calls. The result is used. 29169746Smsmith */ 29287031Smsmith goto ResultUsed; 29387031Smsmith 29487031Smsmith case AML_CLASS_NAMED_OBJECT: 29587031Smsmith 29699679Siwasaki if ((Op->Common.Parent->Common.AmlOpcode == AML_REGION_OP) || 29799679Siwasaki (Op->Common.Parent->Common.AmlOpcode == AML_DATA_REGION_OP) || 29899679Siwasaki (Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || 29999679Siwasaki (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP) || 30099679Siwasaki (Op->Common.Parent->Common.AmlOpcode == AML_BUFFER_OP) || 301193267Sjkim (Op->Common.Parent->Common.AmlOpcode == AML_INT_EVAL_SUBTREE_OP) || 302193267Sjkim (Op->Common.Parent->Common.AmlOpcode == AML_BANK_FIELD_OP)) 30369746Smsmith { 30487031Smsmith /* 30587031Smsmith * These opcodes allow TermArg(s) as operands and therefore 306241973Sjkim * the operands can be method calls. The result is used. 30787031Smsmith */ 30887031Smsmith goto ResultUsed; 30969746Smsmith } 31069746Smsmith 31187031Smsmith goto ResultNotUsed; 31267754Smsmith 31367754Smsmith default: 31499146Siwasaki /* 31599146Siwasaki * In all other cases. the parent will actually use the return 31699146Siwasaki * object, so keep it. 31799146Siwasaki */ 31887031Smsmith goto ResultUsed; 31967754Smsmith } 32067754Smsmith 32187031Smsmith 32287031SmsmithResultUsed: 323151937Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 324151937Sjkim "Result of [%s] used by Parent [%s] Op=%p\n", 325151937Sjkim AcpiPsGetOpcodeName (Op->Common.AmlOpcode), 326151937Sjkim AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op)); 32787031Smsmith 328246849Sjkim return_UINT8 (TRUE); 32987031Smsmith 33087031Smsmith 33187031SmsmithResultNotUsed: 332151937Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 333151937Sjkim "Result of [%s] not used by Parent [%s] Op=%p\n", 334151937Sjkim AcpiPsGetOpcodeName (Op->Common.AmlOpcode), 335151937Sjkim AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op)); 33687031Smsmith 337246849Sjkim return_UINT8 (FALSE); 33867754Smsmith} 33967754Smsmith 34067754Smsmith 34167754Smsmith/******************************************************************************* 34267754Smsmith * 34367754Smsmith * FUNCTION: AcpiDsDeleteResultIfNotUsed 34467754Smsmith * 345138287Smarks * PARAMETERS: Op - Current parse Op 346138287Smarks * ResultObj - Result of the operation 347138287Smarks * WalkState - Current state 34867754Smsmith * 34967754Smsmith * RETURN: Status 35067754Smsmith * 351241973Sjkim * DESCRIPTION: Used after interpretation of an opcode. If there is an internal 35267754Smsmith * result descriptor, check if the parent opcode will actually use 353241973Sjkim * this result. If not, delete the result now so that it will 35467754Smsmith * not become orphaned. 35567754Smsmith * 35667754Smsmith ******************************************************************************/ 35767754Smsmith 35867754Smsmithvoid 35967754SmsmithAcpiDsDeleteResultIfNotUsed ( 36067754Smsmith ACPI_PARSE_OBJECT *Op, 36167754Smsmith ACPI_OPERAND_OBJECT *ResultObj, 36267754Smsmith ACPI_WALK_STATE *WalkState) 36367754Smsmith{ 36467754Smsmith ACPI_OPERAND_OBJECT *ObjDesc; 36567754Smsmith ACPI_STATUS Status; 36667754Smsmith 36767754Smsmith 368167802Sjkim ACPI_FUNCTION_TRACE_PTR (DsDeleteResultIfNotUsed, ResultObj); 36967754Smsmith 37067754Smsmith 37167754Smsmith if (!Op) 37267754Smsmith { 373167802Sjkim ACPI_ERROR ((AE_INFO, "Null Op")); 37467754Smsmith return_VOID; 37567754Smsmith } 37667754Smsmith 37767754Smsmith if (!ResultObj) 37867754Smsmith { 37967754Smsmith return_VOID; 38067754Smsmith } 38167754Smsmith 38267754Smsmith if (!AcpiDsIsResultUsed (Op, WalkState)) 38367754Smsmith { 384151937Sjkim /* Must pop the result stack (ObjDesc should be equal to ResultObj) */ 385151937Sjkim 38669746Smsmith Status = AcpiDsResultPop (&ObjDesc, WalkState); 38767754Smsmith if (ACPI_SUCCESS (Status)) 38867754Smsmith { 38977424Smsmith AcpiUtRemoveReference (ResultObj); 39067754Smsmith } 39167754Smsmith } 39267754Smsmith 39367754Smsmith return_VOID; 39467754Smsmith} 39567754Smsmith 39667754Smsmith 39767754Smsmith/******************************************************************************* 39867754Smsmith * 399100966Siwasaki * FUNCTION: AcpiDsResolveOperands 400100966Siwasaki * 401100966Siwasaki * PARAMETERS: WalkState - Current walk state with operands on stack 402100966Siwasaki * 403100966Siwasaki * RETURN: Status 404100966Siwasaki * 405241973Sjkim * DESCRIPTION: Resolve all operands to their values. Used to prepare 406100966Siwasaki * arguments to a control method invocation (a call from one 407100966Siwasaki * method to another.) 408100966Siwasaki * 409100966Siwasaki ******************************************************************************/ 410100966Siwasaki 411100966SiwasakiACPI_STATUS 412100966SiwasakiAcpiDsResolveOperands ( 413100966Siwasaki ACPI_WALK_STATE *WalkState) 414100966Siwasaki{ 415100966Siwasaki UINT32 i; 416100966Siwasaki ACPI_STATUS Status = AE_OK; 417100966Siwasaki 418100966Siwasaki 419167802Sjkim ACPI_FUNCTION_TRACE_PTR (DsResolveOperands, WalkState); 420100966Siwasaki 421100966Siwasaki 422100966Siwasaki /* 423100966Siwasaki * Attempt to resolve each of the valid operands 424241973Sjkim * Method arguments are passed by reference, not by value. This means 425126372Snjl * that the actual objects are passed, not copies of the objects. 426100966Siwasaki */ 427100966Siwasaki for (i = 0; i < WalkState->NumOperands; i++) 428100966Siwasaki { 429100966Siwasaki Status = AcpiExResolveToValue (&WalkState->Operands[i], WalkState); 430100966Siwasaki if (ACPI_FAILURE (Status)) 431100966Siwasaki { 432100966Siwasaki break; 433100966Siwasaki } 434100966Siwasaki } 435100966Siwasaki 436100966Siwasaki return_ACPI_STATUS (Status); 437100966Siwasaki} 438107325Siwasaki 439107325Siwasaki 440107325Siwasaki/******************************************************************************* 441107325Siwasaki * 442107325Siwasaki * FUNCTION: AcpiDsClearOperands 443107325Siwasaki * 444107325Siwasaki * PARAMETERS: WalkState - Current walk state with operands on stack 445107325Siwasaki * 446107325Siwasaki * RETURN: None 447107325Siwasaki * 448107325Siwasaki * DESCRIPTION: Clear all operands on the current walk state operand stack. 449107325Siwasaki * 450107325Siwasaki ******************************************************************************/ 451107325Siwasaki 452107325Siwasakivoid 453107325SiwasakiAcpiDsClearOperands ( 454107325Siwasaki ACPI_WALK_STATE *WalkState) 455107325Siwasaki{ 456107325Siwasaki UINT32 i; 457107325Siwasaki 458107325Siwasaki 459167802Sjkim ACPI_FUNCTION_TRACE_PTR (DsClearOperands, WalkState); 460107325Siwasaki 461107325Siwasaki 462151937Sjkim /* Remove a reference on each operand on the stack */ 463151937Sjkim 464107325Siwasaki for (i = 0; i < WalkState->NumOperands; i++) 465107325Siwasaki { 466107325Siwasaki /* 467107325Siwasaki * Remove a reference to all operands, including both 468107325Siwasaki * "Arguments" and "Targets". 469107325Siwasaki */ 470107325Siwasaki AcpiUtRemoveReference (WalkState->Operands[i]); 471107325Siwasaki WalkState->Operands[i] = NULL; 472107325Siwasaki } 473107325Siwasaki 474107325Siwasaki WalkState->NumOperands = 0; 475107325Siwasaki return_VOID; 476107325Siwasaki} 477100966Siwasaki#endif 478100966Siwasaki 479100966Siwasaki 480100966Siwasaki/******************************************************************************* 481100966Siwasaki * 48267754Smsmith * FUNCTION: AcpiDsCreateOperand 48367754Smsmith * 484138287Smarks * PARAMETERS: WalkState - Current walk state 485138287Smarks * Arg - Parse object for the argument 486138287Smarks * ArgIndex - Which argument (zero based) 48767754Smsmith * 48867754Smsmith * RETURN: Status 48967754Smsmith * 49067754Smsmith * DESCRIPTION: Translate a parse tree object that is an argument to an AML 491241973Sjkim * opcode to the equivalent interpreter object. This may include 49267754Smsmith * looking up a name or entering a new name into the internal 49367754Smsmith * namespace. 49467754Smsmith * 49567754Smsmith ******************************************************************************/ 49667754Smsmith 49767754SmsmithACPI_STATUS 49867754SmsmithAcpiDsCreateOperand ( 49967754Smsmith ACPI_WALK_STATE *WalkState, 50069746Smsmith ACPI_PARSE_OBJECT *Arg, 50169746Smsmith UINT32 ArgIndex) 50267754Smsmith{ 50367754Smsmith ACPI_STATUS Status = AE_OK; 504114237Snjl char *NameString; 50567754Smsmith UINT32 NameLength; 50667754Smsmith ACPI_OPERAND_OBJECT *ObjDesc; 50767754Smsmith ACPI_PARSE_OBJECT *ParentOp; 50867754Smsmith UINT16 Opcode; 50991116Smsmith ACPI_INTERPRETER_MODE InterpreterMode; 51083174Smsmith const ACPI_OPCODE_INFO *OpInfo; 51167754Smsmith 51267754Smsmith 513167802Sjkim ACPI_FUNCTION_TRACE_PTR (DsCreateOperand, Arg); 51467754Smsmith 51567754Smsmith 51667754Smsmith /* A valid name must be looked up in the namespace */ 51767754Smsmith 51899679Siwasaki if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && 519167802Sjkim (Arg->Common.Value.String) && 520167802Sjkim !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK)) 52167754Smsmith { 52282367Smsmith ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", Arg)); 52367754Smsmith 52467754Smsmith /* Get the entire name string from the AML stream */ 52567754Smsmith 52699679Siwasaki Status = AcpiExGetNameString (ACPI_TYPE_ANY, Arg->Common.Value.Buffer, 52777424Smsmith &NameString, &NameLength); 52867754Smsmith 52967754Smsmith if (ACPI_FAILURE (Status)) 53067754Smsmith { 53167754Smsmith return_ACPI_STATUS (Status); 53267754Smsmith } 53367754Smsmith 534151937Sjkim /* All prefixes have been handled, and the name is in NameString */ 53567754Smsmith 53667754Smsmith /* 537241973Sjkim * Special handling for BufferField declarations. This is a deferred 538123315Snjl * opcode that unfortunately defines the field name as the last 539241973Sjkim * parameter instead of the first. We get here when we are performing 540123315Snjl * the deferred execution, so the actual name of the field is already 541241973Sjkim * in the namespace. We don't want to attempt to look it up again 542123315Snjl * because we may be executing in a different scope than where the 543123315Snjl * actual opcode exists. 54467754Smsmith */ 545123315Snjl if ((WalkState->DeferredNode) && 546123315Snjl (WalkState->DeferredNode->Type == ACPI_TYPE_BUFFER_FIELD) && 547167802Sjkim (ArgIndex == (UINT32) ((WalkState->Opcode == AML_CREATE_FIELD_OP) ? 3 : 2))) 54867754Smsmith { 549151937Sjkim ObjDesc = ACPI_CAST_PTR ( 550151937Sjkim ACPI_OPERAND_OBJECT, WalkState->DeferredNode); 551123315Snjl Status = AE_OK; 55267754Smsmith } 553123315Snjl else /* All other opcodes */ 55467754Smsmith { 555123315Snjl /* 556123315Snjl * Differentiate between a namespace "create" operation 557123315Snjl * versus a "lookup" operation (IMODE_LOAD_PASS2 vs. 558123315Snjl * IMODE_EXECUTE) in order to support the creation of 559123315Snjl * namespace objects during the execution of control methods. 560123315Snjl */ 561123315Snjl ParentOp = Arg->Common.Parent; 562123315Snjl OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode); 563123315Snjl if ((OpInfo->Flags & AML_NSNODE) && 564123315Snjl (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) && 565123315Snjl (ParentOp->Common.AmlOpcode != AML_REGION_OP) && 566123315Snjl (ParentOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP)) 567123315Snjl { 568123315Snjl /* Enter name into namespace if not found */ 56967754Smsmith 570123315Snjl InterpreterMode = ACPI_IMODE_LOAD_PASS2; 571123315Snjl } 572123315Snjl else 573123315Snjl { 574123315Snjl /* Return a failure if name not found */ 57567754Smsmith 576123315Snjl InterpreterMode = ACPI_IMODE_EXECUTE; 577123315Snjl } 578123315Snjl 579123315Snjl Status = AcpiNsLookup (WalkState->ScopeInfo, NameString, 580151937Sjkim ACPI_TYPE_ANY, InterpreterMode, 581151937Sjkim ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, 582151937Sjkim WalkState, 583151937Sjkim ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &ObjDesc)); 584123315Snjl /* 585123315Snjl * The only case where we pass through (ignore) a NOT_FOUND 586123315Snjl * error is for the CondRefOf opcode. 587123315Snjl */ 588123315Snjl if (Status == AE_NOT_FOUND) 58967754Smsmith { 590123315Snjl if (ParentOp->Common.AmlOpcode == AML_COND_REF_OF_OP) 591123315Snjl { 592123315Snjl /* 593123315Snjl * For the Conditional Reference op, it's OK if 594123315Snjl * the name is not found; We just need a way to 595123315Snjl * indicate this to the interpreter, set the 596123315Snjl * object to the root 597123315Snjl */ 598151937Sjkim ObjDesc = ACPI_CAST_PTR ( 599151937Sjkim ACPI_OPERAND_OBJECT, AcpiGbl_RootNode); 600123315Snjl Status = AE_OK; 601123315Snjl } 602281687Sjkim else if (ParentOp->Common.AmlOpcode == AML_EXTERNAL_OP) 603281687Sjkim { 604281687Sjkim /* TBD: May only be temporary */ 605281687Sjkim 606281687Sjkim ObjDesc = AcpiUtCreateStringObject ((ACPI_SIZE) NameLength); 607281687Sjkim 608281687Sjkim ACPI_STRNCPY (ObjDesc->String.Pointer, NameString, NameLength); 609281687Sjkim Status = AE_OK; 610281687Sjkim } 611123315Snjl else 612123315Snjl { 613123315Snjl /* 614123315Snjl * We just plain didn't find it -- which is a 615123315Snjl * very serious error at this point 616123315Snjl */ 617123315Snjl Status = AE_AML_NAME_NOT_FOUND; 618123315Snjl } 61967754Smsmith } 62067754Smsmith 621123315Snjl if (ACPI_FAILURE (Status)) 62267754Smsmith { 623167802Sjkim ACPI_ERROR_NAMESPACE (NameString, Status); 62467754Smsmith } 62567754Smsmith } 62667754Smsmith 62791116Smsmith /* Free the namestring created above */ 62891116Smsmith 629167802Sjkim ACPI_FREE (NameString); 63091116Smsmith 63167754Smsmith /* Check status from the lookup */ 63267754Smsmith 63367754Smsmith if (ACPI_FAILURE (Status)) 63467754Smsmith { 63567754Smsmith return_ACPI_STATUS (Status); 63667754Smsmith } 63767754Smsmith 63867754Smsmith /* Put the resulting object onto the current object stack */ 63967754Smsmith 64067754Smsmith Status = AcpiDsObjStackPush (ObjDesc, WalkState); 64167754Smsmith if (ACPI_FAILURE (Status)) 64267754Smsmith { 64367754Smsmith return_ACPI_STATUS (Status); 64467754Smsmith } 64591116Smsmith ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState)); 64667754Smsmith } 64767754Smsmith else 64867754Smsmith { 64967754Smsmith /* Check for null name case */ 65067754Smsmith 651167802Sjkim if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && 652167802Sjkim !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK)) 65367754Smsmith { 65467754Smsmith /* 65567754Smsmith * If the name is null, this means that this is an 65667754Smsmith * optional result parameter that was not specified 657241973Sjkim * in the original ASL. Create a Zero Constant for a 658241973Sjkim * placeholder. (Store to a constant is a Noop.) 65967754Smsmith */ 66067754Smsmith Opcode = AML_ZERO_OP; /* Has no arguments! */ 66167754Smsmith 662151937Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 663151937Sjkim "Null namepath: Arg=%p\n", Arg)); 66467754Smsmith } 66567754Smsmith else 66667754Smsmith { 66799679Siwasaki Opcode = Arg->Common.AmlOpcode; 66867754Smsmith } 66967754Smsmith 67087031Smsmith /* Get the object type of the argument */ 67167754Smsmith 67287031Smsmith OpInfo = AcpiPsGetOpcodeInfo (Opcode); 673107325Siwasaki if (OpInfo->ObjectType == ACPI_TYPE_INVALID) 67467754Smsmith { 67567754Smsmith return_ACPI_STATUS (AE_NOT_IMPLEMENTED); 67667754Smsmith } 67767754Smsmith 678167802Sjkim if ((OpInfo->Flags & AML_HAS_RETVAL) || (Arg->Common.Flags & ACPI_PARSEOP_IN_STACK)) 67967754Smsmith { 68082367Smsmith ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 681151937Sjkim "Argument previously created, already stacked\n")); 68267754Smsmith 68391116Smsmith ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject ( 68491116Smsmith WalkState->Operands [WalkState->NumOperands - 1], WalkState)); 68567754Smsmith 68667754Smsmith /* 68767754Smsmith * Use value that was already previously returned 68867754Smsmith * by the evaluation of this argument 68967754Smsmith */ 690167802Sjkim Status = AcpiDsResultPop (&ObjDesc, WalkState); 69167754Smsmith if (ACPI_FAILURE (Status)) 69267754Smsmith { 69367754Smsmith /* 69467754Smsmith * Only error is underflow, and this indicates 69567754Smsmith * a missing or null operand! 69667754Smsmith */ 697167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 698167802Sjkim "Missing or null operand")); 69967754Smsmith return_ACPI_STATUS (Status); 70067754Smsmith } 70167754Smsmith } 70267754Smsmith else 70367754Smsmith { 70467754Smsmith /* Create an ACPI_INTERNAL_OBJECT for the argument */ 70567754Smsmith 70687031Smsmith ObjDesc = AcpiUtCreateInternalObject (OpInfo->ObjectType); 70767754Smsmith if (!ObjDesc) 70867754Smsmith { 70967754Smsmith return_ACPI_STATUS (AE_NO_MEMORY); 71067754Smsmith } 71167754Smsmith 71267754Smsmith /* Initialize the new object */ 71367754Smsmith 714151937Sjkim Status = AcpiDsInitObjectFromOp ( 715151937Sjkim WalkState, Arg, Opcode, &ObjDesc); 71667754Smsmith if (ACPI_FAILURE (Status)) 71767754Smsmith { 71877424Smsmith AcpiUtDeleteObjectDesc (ObjDesc); 71967754Smsmith return_ACPI_STATUS (Status); 72067754Smsmith } 72199679Siwasaki } 72267754Smsmith 72367754Smsmith /* Put the operand object on the object stack */ 72467754Smsmith 72567754Smsmith Status = AcpiDsObjStackPush (ObjDesc, WalkState); 72667754Smsmith if (ACPI_FAILURE (Status)) 72767754Smsmith { 72867754Smsmith return_ACPI_STATUS (Status); 72967754Smsmith } 73067754Smsmith 73191116Smsmith ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState)); 73267754Smsmith } 73367754Smsmith 73467754Smsmith return_ACPI_STATUS (AE_OK); 73567754Smsmith} 73667754Smsmith 73767754Smsmith 73867754Smsmith/******************************************************************************* 73967754Smsmith * 74067754Smsmith * FUNCTION: AcpiDsCreateOperands 74167754Smsmith * 742151937Sjkim * PARAMETERS: WalkState - Current state 743151937Sjkim * FirstArg - First argument of a parser argument tree 74467754Smsmith * 74567754Smsmith * RETURN: Status 74667754Smsmith * 74767754Smsmith * DESCRIPTION: Convert an operator's arguments from a parse tree format to 74867754Smsmith * namespace objects and place those argument object on the object 74967754Smsmith * stack in preparation for evaluation by the interpreter. 75067754Smsmith * 75167754Smsmith ******************************************************************************/ 75267754Smsmith 75367754SmsmithACPI_STATUS 75467754SmsmithAcpiDsCreateOperands ( 75567754Smsmith ACPI_WALK_STATE *WalkState, 75667754Smsmith ACPI_PARSE_OBJECT *FirstArg) 75767754Smsmith{ 75867754Smsmith ACPI_STATUS Status = AE_OK; 75967754Smsmith ACPI_PARSE_OBJECT *Arg; 760167802Sjkim ACPI_PARSE_OBJECT *Arguments[ACPI_OBJ_NUM_OPERANDS]; 761193267Sjkim UINT32 ArgCount = 0; 762193267Sjkim UINT32 Index = WalkState->NumOperands; 763193267Sjkim UINT32 i; 76467754Smsmith 76567754Smsmith 766167802Sjkim ACPI_FUNCTION_TRACE_PTR (DsCreateOperands, FirstArg); 76767754Smsmith 76883174Smsmith 769167802Sjkim /* Get all arguments in the list */ 77067754Smsmith 77169746Smsmith Arg = FirstArg; 77267754Smsmith while (Arg) 77367754Smsmith { 774167802Sjkim if (Index >= ACPI_OBJ_NUM_OPERANDS) 77567754Smsmith { 776167802Sjkim return_ACPI_STATUS (AE_BAD_DATA); 77767754Smsmith } 77867754Smsmith 779167802Sjkim Arguments[Index] = Arg; 780167802Sjkim WalkState->Operands [Index] = NULL; 78167754Smsmith 78267754Smsmith /* Move on to next argument, if any */ 78367754Smsmith 78499679Siwasaki Arg = Arg->Common.Next; 78569746Smsmith ArgCount++; 786167802Sjkim Index++; 78767754Smsmith } 78867754Smsmith 789281075Sdim ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 790281075Sdim "NumOperands %d, ArgCount %d, Index %d\n", 791281075Sdim WalkState->NumOperands, ArgCount, Index)); 792167802Sjkim 793281075Sdim /* Create the interpreter arguments, in reverse order */ 794167802Sjkim 795281075Sdim Index--; 796167802Sjkim for (i = 0; i < ArgCount; i++) 797167802Sjkim { 798167802Sjkim Arg = Arguments[Index]; 799193267Sjkim WalkState->OperandIndex = (UINT8) Index; 800167802Sjkim 801167802Sjkim Status = AcpiDsCreateOperand (WalkState, Arg, Index); 802167802Sjkim if (ACPI_FAILURE (Status)) 803167802Sjkim { 804167802Sjkim goto Cleanup; 805167802Sjkim } 806167802Sjkim 807281075Sdim ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 808281075Sdim "Created Arg #%u (%p) %u args total\n", 809281075Sdim Index, Arg, ArgCount)); 810167802Sjkim Index--; 811167802Sjkim } 812167802Sjkim 81367754Smsmith return_ACPI_STATUS (Status); 81467754Smsmith 81567754Smsmith 81667754SmsmithCleanup: 81767754Smsmith /* 81867754Smsmith * We must undo everything done above; meaning that we must 81967754Smsmith * pop everything off of the operand stack and delete those 82067754Smsmith * objects 82167754Smsmith */ 822167802Sjkim AcpiDsObjStackPopAndDelete (ArgCount, WalkState); 82367754Smsmith 824209746Sjkim ACPI_EXCEPTION ((AE_INFO, Status, "While creating Arg %u", Index)); 82567754Smsmith return_ACPI_STATUS (Status); 82667754Smsmith} 82767754Smsmith 82867754Smsmith 829167802Sjkim/***************************************************************************** 830167802Sjkim * 831167802Sjkim * FUNCTION: AcpiDsEvaluateNamePath 832167802Sjkim * 833167802Sjkim * PARAMETERS: WalkState - Current state of the parse tree walk, 834167802Sjkim * the opcode of current operation should be 835167802Sjkim * AML_INT_NAMEPATH_OP 836167802Sjkim * 837167802Sjkim * RETURN: Status 838167802Sjkim * 839167802Sjkim * DESCRIPTION: Translate the -NamePath- parse tree object to the equivalent 840167802Sjkim * interpreter object, convert it to value, if needed, duplicate 841167802Sjkim * it, if needed, and push it onto the current result stack. 842167802Sjkim * 843167802Sjkim ****************************************************************************/ 844167802Sjkim 845167802SjkimACPI_STATUS 846167802SjkimAcpiDsEvaluateNamePath ( 847167802Sjkim ACPI_WALK_STATE *WalkState) 848167802Sjkim{ 849167802Sjkim ACPI_STATUS Status = AE_OK; 850167802Sjkim ACPI_PARSE_OBJECT *Op = WalkState->Op; 851167802Sjkim ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 852167802Sjkim ACPI_OPERAND_OBJECT *NewObjDesc; 853167802Sjkim UINT8 Type; 854167802Sjkim 855167802Sjkim 856167802Sjkim ACPI_FUNCTION_TRACE_PTR (DsEvaluateNamePath, WalkState); 857167802Sjkim 858167802Sjkim 859167802Sjkim if (!Op->Common.Parent) 860167802Sjkim { 861167802Sjkim /* This happens after certain exception processing */ 862167802Sjkim 863167802Sjkim goto Exit; 864167802Sjkim } 865167802Sjkim 866167802Sjkim if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || 867167802Sjkim (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP) || 868167802Sjkim (Op->Common.Parent->Common.AmlOpcode == AML_REF_OF_OP)) 869167802Sjkim { 870167802Sjkim /* TBD: Should we specify this feature as a bit of OpInfo->Flags of these opcodes? */ 871167802Sjkim 872167802Sjkim goto Exit; 873167802Sjkim } 874167802Sjkim 875167802Sjkim Status = AcpiDsCreateOperand (WalkState, Op, 0); 876167802Sjkim if (ACPI_FAILURE (Status)) 877167802Sjkim { 878167802Sjkim goto Exit; 879167802Sjkim } 880167802Sjkim 881167802Sjkim if (Op->Common.Flags & ACPI_PARSEOP_TARGET) 882167802Sjkim { 883167802Sjkim NewObjDesc = *Operand; 884167802Sjkim goto PushResult; 885167802Sjkim } 886167802Sjkim 887193267Sjkim Type = (*Operand)->Common.Type; 888167802Sjkim 889167802Sjkim Status = AcpiExResolveToValue (Operand, WalkState); 890167802Sjkim if (ACPI_FAILURE (Status)) 891167802Sjkim { 892167802Sjkim goto Exit; 893167802Sjkim } 894167802Sjkim 895167802Sjkim if (Type == ACPI_TYPE_INTEGER) 896167802Sjkim { 897167802Sjkim /* It was incremented by AcpiExResolveToValue */ 898167802Sjkim 899167802Sjkim AcpiUtRemoveReference (*Operand); 900167802Sjkim 901167802Sjkim Status = AcpiUtCopyIobjectToIobject (*Operand, &NewObjDesc, WalkState); 902167802Sjkim if (ACPI_FAILURE (Status)) 903167802Sjkim { 904167802Sjkim goto Exit; 905167802Sjkim } 906167802Sjkim } 907167802Sjkim else 908167802Sjkim { 909167802Sjkim /* 910167802Sjkim * The object either was anew created or is 911167802Sjkim * a Namespace node - don't decrement it. 912167802Sjkim */ 913167802Sjkim NewObjDesc = *Operand; 914167802Sjkim } 915167802Sjkim 916167802Sjkim /* Cleanup for name-path operand */ 917167802Sjkim 918167802Sjkim Status = AcpiDsObjStackPop (1, WalkState); 919167802Sjkim if (ACPI_FAILURE (Status)) 920167802Sjkim { 921167802Sjkim WalkState->ResultObj = NewObjDesc; 922167802Sjkim goto Exit; 923167802Sjkim } 924167802Sjkim 925167802SjkimPushResult: 926167802Sjkim 927167802Sjkim WalkState->ResultObj = NewObjDesc; 928167802Sjkim 929167802Sjkim Status = AcpiDsResultPush (WalkState->ResultObj, WalkState); 930167802Sjkim if (ACPI_SUCCESS (Status)) 931167802Sjkim { 932167802Sjkim /* Force to take it from stack */ 933167802Sjkim 934167802Sjkim Op->Common.Flags |= ACPI_PARSEOP_IN_STACK; 935167802Sjkim } 936167802Sjkim 937167802SjkimExit: 938167802Sjkim 939167802Sjkim return_ACPI_STATUS (Status); 940167802Sjkim} 941