128c506b8Sjruoho /*******************************************************************************
228c506b8Sjruoho *
328c506b8Sjruoho * Module Name: dsutils - Dispatcher utilities
428c506b8Sjruoho *
528c506b8Sjruoho ******************************************************************************/
628c506b8Sjruoho
7124f4c82Sjruoho /*
8*2c7d7e3cSchristos * Copyright (C) 2000 - 2023, Intel Corp.
928c506b8Sjruoho * All rights reserved.
1028c506b8Sjruoho *
11124f4c82Sjruoho * Redistribution and use in source and binary forms, with or without
12124f4c82Sjruoho * modification, are permitted provided that the following conditions
13124f4c82Sjruoho * are met:
14124f4c82Sjruoho * 1. Redistributions of source code must retain the above copyright
15124f4c82Sjruoho * notice, this list of conditions, and the following disclaimer,
16124f4c82Sjruoho * without modification.
17124f4c82Sjruoho * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18124f4c82Sjruoho * substantially similar to the "NO WARRANTY" disclaimer below
19124f4c82Sjruoho * ("Disclaimer") and any redistribution must be conditioned upon
20124f4c82Sjruoho * including a substantially similar Disclaimer requirement for further
21124f4c82Sjruoho * binary redistribution.
22124f4c82Sjruoho * 3. Neither the names of the above-listed copyright holders nor the names
23124f4c82Sjruoho * of any contributors may be used to endorse or promote products derived
24124f4c82Sjruoho * from this software without specific prior written permission.
2528c506b8Sjruoho *
26124f4c82Sjruoho * Alternatively, this software may be distributed under the terms of the
27124f4c82Sjruoho * GNU General Public License ("GPL") version 2 as published by the Free
28124f4c82Sjruoho * Software Foundation.
2928c506b8Sjruoho *
30124f4c82Sjruoho * NO WARRANTY
31124f4c82Sjruoho * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32124f4c82Sjruoho * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3398244dcfSchristos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34124f4c82Sjruoho * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35124f4c82Sjruoho * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36124f4c82Sjruoho * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37124f4c82Sjruoho * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38124f4c82Sjruoho * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39124f4c82Sjruoho * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40124f4c82Sjruoho * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41124f4c82Sjruoho * POSSIBILITY OF SUCH DAMAGES.
42124f4c82Sjruoho */
4328c506b8Sjruoho
4428c506b8Sjruoho #include "acpi.h"
4528c506b8Sjruoho #include "accommon.h"
4628c506b8Sjruoho #include "acparser.h"
4728c506b8Sjruoho #include "amlcode.h"
4828c506b8Sjruoho #include "acdispat.h"
4928c506b8Sjruoho #include "acinterp.h"
5028c506b8Sjruoho #include "acnamesp.h"
5128c506b8Sjruoho #include "acdebug.h"
5228c506b8Sjruoho
5328c506b8Sjruoho #define _COMPONENT ACPI_DISPATCHER
5428c506b8Sjruoho ACPI_MODULE_NAME ("dsutils")
5528c506b8Sjruoho
5628c506b8Sjruoho
5728c506b8Sjruoho /*******************************************************************************
5828c506b8Sjruoho *
5928c506b8Sjruoho * FUNCTION: AcpiDsClearImplicitReturn
6028c506b8Sjruoho *
6128c506b8Sjruoho * PARAMETERS: WalkState - Current State
6228c506b8Sjruoho *
6328c506b8Sjruoho * RETURN: None.
6428c506b8Sjruoho *
6528c506b8Sjruoho * DESCRIPTION: Clear and remove a reference on an implicit return value. Used
6628c506b8Sjruoho * to delete "stale" return values (if enabled, the return value
6728c506b8Sjruoho * from every operator is saved at least momentarily, in case the
6828c506b8Sjruoho * parent method exits.)
6928c506b8Sjruoho *
7028c506b8Sjruoho ******************************************************************************/
7128c506b8Sjruoho
7228c506b8Sjruoho void
AcpiDsClearImplicitReturn(ACPI_WALK_STATE * WalkState)7328c506b8Sjruoho AcpiDsClearImplicitReturn (
7428c506b8Sjruoho ACPI_WALK_STATE *WalkState)
7528c506b8Sjruoho {
7628c506b8Sjruoho ACPI_FUNCTION_NAME (DsClearImplicitReturn);
7728c506b8Sjruoho
7828c506b8Sjruoho
7928c506b8Sjruoho /*
8028c506b8Sjruoho * Slack must be enabled for this feature
8128c506b8Sjruoho */
8228c506b8Sjruoho if (!AcpiGbl_EnableInterpreterSlack)
8328c506b8Sjruoho {
8428c506b8Sjruoho return;
8528c506b8Sjruoho }
8628c506b8Sjruoho
8728c506b8Sjruoho if (WalkState->ImplicitReturnObj)
8828c506b8Sjruoho {
8928c506b8Sjruoho /*
9028c506b8Sjruoho * Delete any "stale" implicit return. However, in
9128c506b8Sjruoho * complex statements, the implicit return value can be
9228c506b8Sjruoho * bubbled up several levels.
9328c506b8Sjruoho */
9428c506b8Sjruoho ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
9528c506b8Sjruoho "Removing reference on stale implicit return obj %p\n",
9628c506b8Sjruoho WalkState->ImplicitReturnObj));
9728c506b8Sjruoho
9828c506b8Sjruoho AcpiUtRemoveReference (WalkState->ImplicitReturnObj);
9928c506b8Sjruoho WalkState->ImplicitReturnObj = NULL;
10028c506b8Sjruoho }
10128c506b8Sjruoho }
10228c506b8Sjruoho
10328c506b8Sjruoho
10428c506b8Sjruoho /*******************************************************************************
10528c506b8Sjruoho *
10628c506b8Sjruoho * FUNCTION: AcpiDsDoImplicitReturn
10728c506b8Sjruoho *
10828c506b8Sjruoho * PARAMETERS: ReturnDesc - The return value
10928c506b8Sjruoho * WalkState - Current State
11028c506b8Sjruoho * AddReference - True if a reference should be added to the
11128c506b8Sjruoho * return object
11228c506b8Sjruoho *
11328c506b8Sjruoho * RETURN: TRUE if implicit return enabled, FALSE otherwise
11428c506b8Sjruoho *
11528c506b8Sjruoho * DESCRIPTION: Implements the optional "implicit return". We save the result
11628c506b8Sjruoho * of every ASL operator and control method invocation in case the
11728c506b8Sjruoho * parent method exit. Before storing a new return value, we
11828c506b8Sjruoho * delete the previous return value.
11928c506b8Sjruoho *
12028c506b8Sjruoho ******************************************************************************/
12128c506b8Sjruoho
12228c506b8Sjruoho BOOLEAN
AcpiDsDoImplicitReturn(ACPI_OPERAND_OBJECT * ReturnDesc,ACPI_WALK_STATE * WalkState,BOOLEAN AddReference)12328c506b8Sjruoho AcpiDsDoImplicitReturn (
12428c506b8Sjruoho ACPI_OPERAND_OBJECT *ReturnDesc,
12528c506b8Sjruoho ACPI_WALK_STATE *WalkState,
12628c506b8Sjruoho BOOLEAN AddReference)
12728c506b8Sjruoho {
12828c506b8Sjruoho ACPI_FUNCTION_NAME (DsDoImplicitReturn);
12928c506b8Sjruoho
13028c506b8Sjruoho
13128c506b8Sjruoho /*
13228c506b8Sjruoho * Slack must be enabled for this feature, and we must
13328c506b8Sjruoho * have a valid return object
13428c506b8Sjruoho */
13528c506b8Sjruoho if ((!AcpiGbl_EnableInterpreterSlack) ||
13628c506b8Sjruoho (!ReturnDesc))
13728c506b8Sjruoho {
13828c506b8Sjruoho return (FALSE);
13928c506b8Sjruoho }
14028c506b8Sjruoho
14128c506b8Sjruoho ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
14228c506b8Sjruoho "Result %p will be implicitly returned; Prev=%p\n",
14328c506b8Sjruoho ReturnDesc,
14428c506b8Sjruoho WalkState->ImplicitReturnObj));
14528c506b8Sjruoho
14628c506b8Sjruoho /*
14728c506b8Sjruoho * Delete any "stale" implicit return value first. However, in
14828c506b8Sjruoho * complex statements, the implicit return value can be
14928c506b8Sjruoho * bubbled up several levels, so we don't clear the value if it
15028c506b8Sjruoho * is the same as the ReturnDesc.
15128c506b8Sjruoho */
15228c506b8Sjruoho if (WalkState->ImplicitReturnObj)
15328c506b8Sjruoho {
15428c506b8Sjruoho if (WalkState->ImplicitReturnObj == ReturnDesc)
15528c506b8Sjruoho {
15628c506b8Sjruoho return (TRUE);
15728c506b8Sjruoho }
15828c506b8Sjruoho AcpiDsClearImplicitReturn (WalkState);
15928c506b8Sjruoho }
16028c506b8Sjruoho
16128c506b8Sjruoho /* Save the implicit return value, add a reference if requested */
16228c506b8Sjruoho
16328c506b8Sjruoho WalkState->ImplicitReturnObj = ReturnDesc;
16428c506b8Sjruoho if (AddReference)
16528c506b8Sjruoho {
16628c506b8Sjruoho AcpiUtAddReference (ReturnDesc);
16728c506b8Sjruoho }
16828c506b8Sjruoho
16928c506b8Sjruoho return (TRUE);
17028c506b8Sjruoho }
17128c506b8Sjruoho
17228c506b8Sjruoho
17328c506b8Sjruoho /*******************************************************************************
17428c506b8Sjruoho *
17528c506b8Sjruoho * FUNCTION: AcpiDsIsResultUsed
17628c506b8Sjruoho *
17728c506b8Sjruoho * PARAMETERS: Op - Current Op
17828c506b8Sjruoho * WalkState - Current State
17928c506b8Sjruoho *
18028c506b8Sjruoho * RETURN: TRUE if result is used, FALSE otherwise
18128c506b8Sjruoho *
18228c506b8Sjruoho * DESCRIPTION: Check if a result object will be used by the parent
18328c506b8Sjruoho *
18428c506b8Sjruoho ******************************************************************************/
18528c506b8Sjruoho
18628c506b8Sjruoho BOOLEAN
AcpiDsIsResultUsed(ACPI_PARSE_OBJECT * Op,ACPI_WALK_STATE * WalkState)18728c506b8Sjruoho AcpiDsIsResultUsed (
18828c506b8Sjruoho ACPI_PARSE_OBJECT *Op,
18928c506b8Sjruoho ACPI_WALK_STATE *WalkState)
19028c506b8Sjruoho {
19128c506b8Sjruoho const ACPI_OPCODE_INFO *ParentInfo;
19228c506b8Sjruoho
19328c506b8Sjruoho ACPI_FUNCTION_TRACE_PTR (DsIsResultUsed, Op);
19428c506b8Sjruoho
19528c506b8Sjruoho
19628c506b8Sjruoho /* Must have both an Op and a Result Object */
19728c506b8Sjruoho
19828c506b8Sjruoho if (!Op)
19928c506b8Sjruoho {
20028c506b8Sjruoho ACPI_ERROR ((AE_INFO, "Null Op"));
20128c506b8Sjruoho return_UINT8 (TRUE);
20228c506b8Sjruoho }
20328c506b8Sjruoho
20428c506b8Sjruoho /*
20528c506b8Sjruoho * We know that this operator is not a
20628c506b8Sjruoho * Return() operator (would not come here.) The following code is the
20728c506b8Sjruoho * optional support for a so-called "implicit return". Some AML code
20828c506b8Sjruoho * assumes that the last value of the method is "implicitly" returned
20928c506b8Sjruoho * to the caller. Just save the last result as the return value.
21028c506b8Sjruoho * NOTE: this is optional because the ASL language does not actually
21128c506b8Sjruoho * support this behavior.
21228c506b8Sjruoho */
21328c506b8Sjruoho (void) AcpiDsDoImplicitReturn (WalkState->ResultObj, WalkState, TRUE);
21428c506b8Sjruoho
21528c506b8Sjruoho /*
21628c506b8Sjruoho * Now determine if the parent will use the result
21728c506b8Sjruoho *
21828c506b8Sjruoho * If there is no parent, or the parent is a ScopeOp, we are executing
21928c506b8Sjruoho * at the method level. An executing method typically has no parent,
22028c506b8Sjruoho * since each method is parsed separately. A method invoked externally
22128c506b8Sjruoho * via ExecuteControlMethod has a ScopeOp as the parent.
22228c506b8Sjruoho */
22328c506b8Sjruoho if ((!Op->Common.Parent) ||
22428c506b8Sjruoho (Op->Common.Parent->Common.AmlOpcode == AML_SCOPE_OP))
22528c506b8Sjruoho {
22628c506b8Sjruoho /* No parent, the return value cannot possibly be used */
22728c506b8Sjruoho
22828c506b8Sjruoho ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
22928c506b8Sjruoho "At Method level, result of [%s] not used\n",
23028c506b8Sjruoho AcpiPsGetOpcodeName (Op->Common.AmlOpcode)));
23128c506b8Sjruoho return_UINT8 (FALSE);
23228c506b8Sjruoho }
23328c506b8Sjruoho
23428c506b8Sjruoho /* Get info on the parent. The RootOp is AML_SCOPE */
23528c506b8Sjruoho
23628c506b8Sjruoho ParentInfo = AcpiPsGetOpcodeInfo (Op->Common.Parent->Common.AmlOpcode);
23728c506b8Sjruoho if (ParentInfo->Class == AML_CLASS_UNKNOWN)
23828c506b8Sjruoho {
23928c506b8Sjruoho ACPI_ERROR ((AE_INFO,
24028c506b8Sjruoho "Unknown parent opcode Op=%p", Op));
24128c506b8Sjruoho return_UINT8 (FALSE);
24228c506b8Sjruoho }
24328c506b8Sjruoho
24428c506b8Sjruoho /*
24528c506b8Sjruoho * Decide what to do with the result based on the parent. If
24628c506b8Sjruoho * the parent opcode will not use the result, delete the object.
24728c506b8Sjruoho * Otherwise leave it as is, it will be deleted when it is used
24828c506b8Sjruoho * as an operand later.
24928c506b8Sjruoho */
25028c506b8Sjruoho switch (ParentInfo->Class)
25128c506b8Sjruoho {
25228c506b8Sjruoho case AML_CLASS_CONTROL:
25328c506b8Sjruoho
25428c506b8Sjruoho switch (Op->Common.Parent->Common.AmlOpcode)
25528c506b8Sjruoho {
25628c506b8Sjruoho case AML_RETURN_OP:
25728c506b8Sjruoho
25828c506b8Sjruoho /* Never delete the return value associated with a return opcode */
25928c506b8Sjruoho
26028c506b8Sjruoho goto ResultUsed;
26128c506b8Sjruoho
26228c506b8Sjruoho case AML_IF_OP:
26328c506b8Sjruoho case AML_WHILE_OP:
26428c506b8Sjruoho /*
26528c506b8Sjruoho * If we are executing the predicate AND this is the predicate op,
26628c506b8Sjruoho * we will use the return value
26728c506b8Sjruoho */
26881bd9c9cSchristos if ((WalkState->ControlState->Common.State ==
26981bd9c9cSchristos ACPI_CONTROL_PREDICATE_EXECUTING) &&
27028c506b8Sjruoho (WalkState->ControlState->Control.PredicateOp == Op))
27128c506b8Sjruoho {
27228c506b8Sjruoho goto ResultUsed;
27328c506b8Sjruoho }
27428c506b8Sjruoho break;
27528c506b8Sjruoho
27628c506b8Sjruoho default:
277ff4a156dSchristos
27828c506b8Sjruoho /* Ignore other control opcodes */
279ff4a156dSchristos
28028c506b8Sjruoho break;
28128c506b8Sjruoho }
28228c506b8Sjruoho
28328c506b8Sjruoho /* The general control opcode returns no result */
28428c506b8Sjruoho
28528c506b8Sjruoho goto ResultNotUsed;
28628c506b8Sjruoho
28728c506b8Sjruoho case AML_CLASS_CREATE:
28828c506b8Sjruoho /*
28928c506b8Sjruoho * These opcodes allow TermArg(s) as operands and therefore
29028c506b8Sjruoho * the operands can be method calls. The result is used.
29128c506b8Sjruoho */
29228c506b8Sjruoho goto ResultUsed;
29328c506b8Sjruoho
29428c506b8Sjruoho case AML_CLASS_NAMED_OBJECT:
29528c506b8Sjruoho
29628c506b8Sjruoho if ((Op->Common.Parent->Common.AmlOpcode == AML_REGION_OP) ||
29728c506b8Sjruoho (Op->Common.Parent->Common.AmlOpcode == AML_DATA_REGION_OP) ||
29828c506b8Sjruoho (Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
29928c506b8Sjruoho (Op->Common.Parent->Common.AmlOpcode == AML_BUFFER_OP) ||
3008f1e17bdSchristos (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP) ||
30128c506b8Sjruoho (Op->Common.Parent->Common.AmlOpcode == AML_INT_EVAL_SUBTREE_OP) ||
30228c506b8Sjruoho (Op->Common.Parent->Common.AmlOpcode == AML_BANK_FIELD_OP))
30328c506b8Sjruoho {
30428c506b8Sjruoho /*
30528c506b8Sjruoho * These opcodes allow TermArg(s) as operands and therefore
30628c506b8Sjruoho * the operands can be method calls. The result is used.
30728c506b8Sjruoho */
30828c506b8Sjruoho goto ResultUsed;
30928c506b8Sjruoho }
31028c506b8Sjruoho
31128c506b8Sjruoho goto ResultNotUsed;
31228c506b8Sjruoho
31328c506b8Sjruoho default:
31428c506b8Sjruoho /*
31528c506b8Sjruoho * In all other cases. the parent will actually use the return
31628c506b8Sjruoho * object, so keep it.
31728c506b8Sjruoho */
31828c506b8Sjruoho goto ResultUsed;
31928c506b8Sjruoho }
32028c506b8Sjruoho
32128c506b8Sjruoho
32228c506b8Sjruoho ResultUsed:
32328c506b8Sjruoho ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
32428c506b8Sjruoho "Result of [%s] used by Parent [%s] Op=%p\n",
32528c506b8Sjruoho AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
32628c506b8Sjruoho AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op));
32728c506b8Sjruoho
32828c506b8Sjruoho return_UINT8 (TRUE);
32928c506b8Sjruoho
33028c506b8Sjruoho
33128c506b8Sjruoho ResultNotUsed:
33228c506b8Sjruoho ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
33328c506b8Sjruoho "Result of [%s] not used by Parent [%s] Op=%p\n",
33428c506b8Sjruoho AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
33528c506b8Sjruoho AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op));
33628c506b8Sjruoho
33728c506b8Sjruoho return_UINT8 (FALSE);
33828c506b8Sjruoho }
33928c506b8Sjruoho
34028c506b8Sjruoho
34128c506b8Sjruoho /*******************************************************************************
34228c506b8Sjruoho *
34328c506b8Sjruoho * FUNCTION: AcpiDsDeleteResultIfNotUsed
34428c506b8Sjruoho *
34528c506b8Sjruoho * PARAMETERS: Op - Current parse Op
34628c506b8Sjruoho * ResultObj - Result of the operation
34728c506b8Sjruoho * WalkState - Current state
34828c506b8Sjruoho *
34928c506b8Sjruoho * RETURN: Status
35028c506b8Sjruoho *
35128c506b8Sjruoho * DESCRIPTION: Used after interpretation of an opcode. If there is an internal
35228c506b8Sjruoho * result descriptor, check if the parent opcode will actually use
35328c506b8Sjruoho * this result. If not, delete the result now so that it will
35428c506b8Sjruoho * not become orphaned.
35528c506b8Sjruoho *
35628c506b8Sjruoho ******************************************************************************/
35728c506b8Sjruoho
35828c506b8Sjruoho void
AcpiDsDeleteResultIfNotUsed(ACPI_PARSE_OBJECT * Op,ACPI_OPERAND_OBJECT * ResultObj,ACPI_WALK_STATE * WalkState)35928c506b8Sjruoho AcpiDsDeleteResultIfNotUsed (
36028c506b8Sjruoho ACPI_PARSE_OBJECT *Op,
36128c506b8Sjruoho ACPI_OPERAND_OBJECT *ResultObj,
36228c506b8Sjruoho ACPI_WALK_STATE *WalkState)
36328c506b8Sjruoho {
36428c506b8Sjruoho ACPI_OPERAND_OBJECT *ObjDesc;
36528c506b8Sjruoho ACPI_STATUS Status;
36628c506b8Sjruoho
36728c506b8Sjruoho
36828c506b8Sjruoho ACPI_FUNCTION_TRACE_PTR (DsDeleteResultIfNotUsed, ResultObj);
36928c506b8Sjruoho
37028c506b8Sjruoho
37128c506b8Sjruoho if (!Op)
37228c506b8Sjruoho {
37328c506b8Sjruoho ACPI_ERROR ((AE_INFO, "Null Op"));
37428c506b8Sjruoho return_VOID;
37528c506b8Sjruoho }
37628c506b8Sjruoho
37728c506b8Sjruoho if (!ResultObj)
37828c506b8Sjruoho {
37928c506b8Sjruoho return_VOID;
38028c506b8Sjruoho }
38128c506b8Sjruoho
38228c506b8Sjruoho if (!AcpiDsIsResultUsed (Op, WalkState))
38328c506b8Sjruoho {
38428c506b8Sjruoho /* Must pop the result stack (ObjDesc should be equal to ResultObj) */
38528c506b8Sjruoho
38628c506b8Sjruoho Status = AcpiDsResultPop (&ObjDesc, WalkState);
38728c506b8Sjruoho if (ACPI_SUCCESS (Status))
38828c506b8Sjruoho {
38928c506b8Sjruoho AcpiUtRemoveReference (ResultObj);
39028c506b8Sjruoho }
39128c506b8Sjruoho }
39228c506b8Sjruoho
39328c506b8Sjruoho return_VOID;
39428c506b8Sjruoho }
39528c506b8Sjruoho
39628c506b8Sjruoho
39728c506b8Sjruoho /*******************************************************************************
39828c506b8Sjruoho *
39928c506b8Sjruoho * FUNCTION: AcpiDsResolveOperands
40028c506b8Sjruoho *
40128c506b8Sjruoho * PARAMETERS: WalkState - Current walk state with operands on stack
40228c506b8Sjruoho *
40328c506b8Sjruoho * RETURN: Status
40428c506b8Sjruoho *
40528c506b8Sjruoho * DESCRIPTION: Resolve all operands to their values. Used to prepare
40628c506b8Sjruoho * arguments to a control method invocation (a call from one
40728c506b8Sjruoho * method to another.)
40828c506b8Sjruoho *
40928c506b8Sjruoho ******************************************************************************/
41028c506b8Sjruoho
41128c506b8Sjruoho ACPI_STATUS
AcpiDsResolveOperands(ACPI_WALK_STATE * WalkState)41228c506b8Sjruoho AcpiDsResolveOperands (
41328c506b8Sjruoho ACPI_WALK_STATE *WalkState)
41428c506b8Sjruoho {
41528c506b8Sjruoho UINT32 i;
41628c506b8Sjruoho ACPI_STATUS Status = AE_OK;
41728c506b8Sjruoho
41828c506b8Sjruoho
41928c506b8Sjruoho ACPI_FUNCTION_TRACE_PTR (DsResolveOperands, WalkState);
42028c506b8Sjruoho
42128c506b8Sjruoho
42228c506b8Sjruoho /*
42328c506b8Sjruoho * Attempt to resolve each of the valid operands
42428c506b8Sjruoho * Method arguments are passed by reference, not by value. This means
42528c506b8Sjruoho * that the actual objects are passed, not copies of the objects.
42628c506b8Sjruoho */
42728c506b8Sjruoho for (i = 0; i < WalkState->NumOperands; i++)
42828c506b8Sjruoho {
42928c506b8Sjruoho Status = AcpiExResolveToValue (&WalkState->Operands[i], WalkState);
43028c506b8Sjruoho if (ACPI_FAILURE (Status))
43128c506b8Sjruoho {
43228c506b8Sjruoho break;
43328c506b8Sjruoho }
43428c506b8Sjruoho }
43528c506b8Sjruoho
43628c506b8Sjruoho return_ACPI_STATUS (Status);
43728c506b8Sjruoho }
43828c506b8Sjruoho
43928c506b8Sjruoho
44028c506b8Sjruoho /*******************************************************************************
44128c506b8Sjruoho *
44228c506b8Sjruoho * FUNCTION: AcpiDsClearOperands
44328c506b8Sjruoho *
44428c506b8Sjruoho * PARAMETERS: WalkState - Current walk state with operands on stack
44528c506b8Sjruoho *
44628c506b8Sjruoho * RETURN: None
44728c506b8Sjruoho *
44828c506b8Sjruoho * DESCRIPTION: Clear all operands on the current walk state operand stack.
44928c506b8Sjruoho *
45028c506b8Sjruoho ******************************************************************************/
45128c506b8Sjruoho
45228c506b8Sjruoho void
AcpiDsClearOperands(ACPI_WALK_STATE * WalkState)45328c506b8Sjruoho AcpiDsClearOperands (
45428c506b8Sjruoho ACPI_WALK_STATE *WalkState)
45528c506b8Sjruoho {
45628c506b8Sjruoho UINT32 i;
45728c506b8Sjruoho
45828c506b8Sjruoho
45928c506b8Sjruoho ACPI_FUNCTION_TRACE_PTR (DsClearOperands, WalkState);
46028c506b8Sjruoho
46128c506b8Sjruoho
46228c506b8Sjruoho /* Remove a reference on each operand on the stack */
46328c506b8Sjruoho
46428c506b8Sjruoho for (i = 0; i < WalkState->NumOperands; i++)
46528c506b8Sjruoho {
46628c506b8Sjruoho /*
46728c506b8Sjruoho * Remove a reference to all operands, including both
46828c506b8Sjruoho * "Arguments" and "Targets".
46928c506b8Sjruoho */
47028c506b8Sjruoho AcpiUtRemoveReference (WalkState->Operands[i]);
47128c506b8Sjruoho WalkState->Operands[i] = NULL;
47228c506b8Sjruoho }
47328c506b8Sjruoho
47428c506b8Sjruoho WalkState->NumOperands = 0;
47528c506b8Sjruoho return_VOID;
47628c506b8Sjruoho }
47728c506b8Sjruoho
47828c506b8Sjruoho
47928c506b8Sjruoho /*******************************************************************************
48028c506b8Sjruoho *
48128c506b8Sjruoho * FUNCTION: AcpiDsCreateOperand
48228c506b8Sjruoho *
48328c506b8Sjruoho * PARAMETERS: WalkState - Current walk state
48428c506b8Sjruoho * Arg - Parse object for the argument
48528c506b8Sjruoho * ArgIndex - Which argument (zero based)
48628c506b8Sjruoho *
48728c506b8Sjruoho * RETURN: Status
48828c506b8Sjruoho *
48928c506b8Sjruoho * DESCRIPTION: Translate a parse tree object that is an argument to an AML
49028c506b8Sjruoho * opcode to the equivalent interpreter object. This may include
49128c506b8Sjruoho * looking up a name or entering a new name into the internal
49228c506b8Sjruoho * namespace.
49328c506b8Sjruoho *
49428c506b8Sjruoho ******************************************************************************/
49528c506b8Sjruoho
49628c506b8Sjruoho ACPI_STATUS
AcpiDsCreateOperand(ACPI_WALK_STATE * WalkState,ACPI_PARSE_OBJECT * Arg,UINT32 ArgIndex)49728c506b8Sjruoho AcpiDsCreateOperand (
49828c506b8Sjruoho ACPI_WALK_STATE *WalkState,
49928c506b8Sjruoho ACPI_PARSE_OBJECT *Arg,
50028c506b8Sjruoho UINT32 ArgIndex)
50128c506b8Sjruoho {
50228c506b8Sjruoho ACPI_STATUS Status = AE_OK;
50328c506b8Sjruoho char *NameString;
50428c506b8Sjruoho UINT32 NameLength;
50528c506b8Sjruoho ACPI_OPERAND_OBJECT *ObjDesc;
50628c506b8Sjruoho ACPI_PARSE_OBJECT *ParentOp;
50728c506b8Sjruoho UINT16 Opcode;
50828c506b8Sjruoho ACPI_INTERPRETER_MODE InterpreterMode;
50928c506b8Sjruoho const ACPI_OPCODE_INFO *OpInfo;
51028c506b8Sjruoho
51128c506b8Sjruoho
51228c506b8Sjruoho ACPI_FUNCTION_TRACE_PTR (DsCreateOperand, Arg);
51328c506b8Sjruoho
51428c506b8Sjruoho
51528c506b8Sjruoho /* A valid name must be looked up in the namespace */
51628c506b8Sjruoho
51728c506b8Sjruoho if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
51828c506b8Sjruoho (Arg->Common.Value.String) &&
51928c506b8Sjruoho !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
52028c506b8Sjruoho {
52128c506b8Sjruoho ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", Arg));
52228c506b8Sjruoho
52328c506b8Sjruoho /* Get the entire name string from the AML stream */
52428c506b8Sjruoho
52581bd9c9cSchristos Status = AcpiExGetNameString (ACPI_TYPE_ANY,
52681bd9c9cSchristos Arg->Common.Value.Buffer, &NameString, &NameLength);
52728c506b8Sjruoho
52828c506b8Sjruoho if (ACPI_FAILURE (Status))
52928c506b8Sjruoho {
53028c506b8Sjruoho return_ACPI_STATUS (Status);
53128c506b8Sjruoho }
53228c506b8Sjruoho
53328c506b8Sjruoho /* All prefixes have been handled, and the name is in NameString */
53428c506b8Sjruoho
53528c506b8Sjruoho /*
53628c506b8Sjruoho * Special handling for BufferField declarations. This is a deferred
53728c506b8Sjruoho * opcode that unfortunately defines the field name as the last
53828c506b8Sjruoho * parameter instead of the first. We get here when we are performing
53928c506b8Sjruoho * the deferred execution, so the actual name of the field is already
54028c506b8Sjruoho * in the namespace. We don't want to attempt to look it up again
54128c506b8Sjruoho * because we may be executing in a different scope than where the
54228c506b8Sjruoho * actual opcode exists.
54328c506b8Sjruoho */
54428c506b8Sjruoho if ((WalkState->DeferredNode) &&
54528c506b8Sjruoho (WalkState->DeferredNode->Type == ACPI_TYPE_BUFFER_FIELD) &&
54681bd9c9cSchristos (ArgIndex == (UINT32)
54781bd9c9cSchristos ((WalkState->Opcode == AML_CREATE_FIELD_OP) ? 3 : 2)))
54828c506b8Sjruoho {
54928c506b8Sjruoho ObjDesc = ACPI_CAST_PTR (
55028c506b8Sjruoho ACPI_OPERAND_OBJECT, WalkState->DeferredNode);
55128c506b8Sjruoho Status = AE_OK;
55228c506b8Sjruoho }
55328c506b8Sjruoho else /* All other opcodes */
55428c506b8Sjruoho {
55528c506b8Sjruoho /*
55628c506b8Sjruoho * Differentiate between a namespace "create" operation
55728c506b8Sjruoho * versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
55828c506b8Sjruoho * IMODE_EXECUTE) in order to support the creation of
55928c506b8Sjruoho * namespace objects during the execution of control methods.
56028c506b8Sjruoho */
56128c506b8Sjruoho ParentOp = Arg->Common.Parent;
56228c506b8Sjruoho OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode);
56381bd9c9cSchristos
56428c506b8Sjruoho if ((OpInfo->Flags & AML_NSNODE) &&
56528c506b8Sjruoho (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) &&
56628c506b8Sjruoho (ParentOp->Common.AmlOpcode != AML_REGION_OP) &&
56728c506b8Sjruoho (ParentOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP))
56828c506b8Sjruoho {
56928c506b8Sjruoho /* Enter name into namespace if not found */
57028c506b8Sjruoho
57128c506b8Sjruoho InterpreterMode = ACPI_IMODE_LOAD_PASS2;
57228c506b8Sjruoho }
57328c506b8Sjruoho else
57428c506b8Sjruoho {
57528c506b8Sjruoho /* Return a failure if name not found */
57628c506b8Sjruoho
57728c506b8Sjruoho InterpreterMode = ACPI_IMODE_EXECUTE;
57828c506b8Sjruoho }
57928c506b8Sjruoho
58028c506b8Sjruoho Status = AcpiNsLookup (WalkState->ScopeInfo, NameString,
58128c506b8Sjruoho ACPI_TYPE_ANY, InterpreterMode,
58281bd9c9cSchristos ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, WalkState,
58328c506b8Sjruoho ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &ObjDesc));
58428c506b8Sjruoho /*
58528c506b8Sjruoho * The only case where we pass through (ignore) a NOT_FOUND
58628c506b8Sjruoho * error is for the CondRefOf opcode.
58728c506b8Sjruoho */
58828c506b8Sjruoho if (Status == AE_NOT_FOUND)
58928c506b8Sjruoho {
5908f1e17bdSchristos if (ParentOp->Common.AmlOpcode == AML_CONDITIONAL_REF_OF_OP)
59128c506b8Sjruoho {
59228c506b8Sjruoho /*
59328c506b8Sjruoho * For the Conditional Reference op, it's OK if
59428c506b8Sjruoho * the name is not found; We just need a way to
59528c506b8Sjruoho * indicate this to the interpreter, set the
59628c506b8Sjruoho * object to the root
59728c506b8Sjruoho */
59828c506b8Sjruoho ObjDesc = ACPI_CAST_PTR (
59928c506b8Sjruoho ACPI_OPERAND_OBJECT, AcpiGbl_RootNode);
60028c506b8Sjruoho Status = AE_OK;
60128c506b8Sjruoho }
602679c17fdSchristos else if (ParentOp->Common.AmlOpcode == AML_EXTERNAL_OP)
603679c17fdSchristos {
60472abab0cSchristos /*
60572abab0cSchristos * This opcode should never appear here. It is used only
60672abab0cSchristos * by AML disassemblers and is surrounded by an If(0)
60772abab0cSchristos * by the ASL compiler.
60872abab0cSchristos *
60972abab0cSchristos * Therefore, if we see it here, it is a serious error.
61072abab0cSchristos */
61172abab0cSchristos Status = AE_AML_BAD_OPCODE;
612dd6caf1eSchristos }
61328c506b8Sjruoho else
61428c506b8Sjruoho {
61528c506b8Sjruoho /*
61628c506b8Sjruoho * We just plain didn't find it -- which is a
61728c506b8Sjruoho * very serious error at this point
61828c506b8Sjruoho */
61928c506b8Sjruoho Status = AE_AML_NAME_NOT_FOUND;
62028c506b8Sjruoho }
62128c506b8Sjruoho }
62228c506b8Sjruoho
62328c506b8Sjruoho if (ACPI_FAILURE (Status))
62428c506b8Sjruoho {
62525666a51Schristos ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo,
62625666a51Schristos NameString, Status);
62728c506b8Sjruoho }
62828c506b8Sjruoho }
62928c506b8Sjruoho
63028c506b8Sjruoho /* Free the namestring created above */
63128c506b8Sjruoho
63228c506b8Sjruoho ACPI_FREE (NameString);
63328c506b8Sjruoho
63428c506b8Sjruoho /* Check status from the lookup */
63528c506b8Sjruoho
63628c506b8Sjruoho if (ACPI_FAILURE (Status))
63728c506b8Sjruoho {
63828c506b8Sjruoho return_ACPI_STATUS (Status);
63928c506b8Sjruoho }
64028c506b8Sjruoho
64128c506b8Sjruoho /* Put the resulting object onto the current object stack */
64228c506b8Sjruoho
64328c506b8Sjruoho Status = AcpiDsObjStackPush (ObjDesc, WalkState);
64428c506b8Sjruoho if (ACPI_FAILURE (Status))
64528c506b8Sjruoho {
64628c506b8Sjruoho return_ACPI_STATUS (Status);
64728c506b8Sjruoho }
64881bd9c9cSchristos
64981bd9c9cSchristos AcpiDbDisplayArgumentObject (ObjDesc, WalkState);
65028c506b8Sjruoho }
65128c506b8Sjruoho else
65228c506b8Sjruoho {
65328c506b8Sjruoho /* Check for null name case */
65428c506b8Sjruoho
65528c506b8Sjruoho if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
65628c506b8Sjruoho !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
65728c506b8Sjruoho {
65828c506b8Sjruoho /*
65928c506b8Sjruoho * If the name is null, this means that this is an
66028c506b8Sjruoho * optional result parameter that was not specified
66128c506b8Sjruoho * in the original ASL. Create a Zero Constant for a
66228c506b8Sjruoho * placeholder. (Store to a constant is a Noop.)
66328c506b8Sjruoho */
66428c506b8Sjruoho Opcode = AML_ZERO_OP; /* Has no arguments! */
66528c506b8Sjruoho
66628c506b8Sjruoho ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
66728c506b8Sjruoho "Null namepath: Arg=%p\n", Arg));
66828c506b8Sjruoho }
66928c506b8Sjruoho else
67028c506b8Sjruoho {
67128c506b8Sjruoho Opcode = Arg->Common.AmlOpcode;
67228c506b8Sjruoho }
67328c506b8Sjruoho
67428c506b8Sjruoho /* Get the object type of the argument */
67528c506b8Sjruoho
67628c506b8Sjruoho OpInfo = AcpiPsGetOpcodeInfo (Opcode);
67728c506b8Sjruoho if (OpInfo->ObjectType == ACPI_TYPE_INVALID)
67828c506b8Sjruoho {
67928c506b8Sjruoho return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
68028c506b8Sjruoho }
68128c506b8Sjruoho
68281bd9c9cSchristos if ((OpInfo->Flags & AML_HAS_RETVAL) ||
68381bd9c9cSchristos (Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
68428c506b8Sjruoho {
68528c506b8Sjruoho /*
68628c506b8Sjruoho * Use value that was already previously returned
68728c506b8Sjruoho * by the evaluation of this argument
68828c506b8Sjruoho */
68928c506b8Sjruoho Status = AcpiDsResultPop (&ObjDesc, WalkState);
69028c506b8Sjruoho if (ACPI_FAILURE (Status))
69128c506b8Sjruoho {
69228c506b8Sjruoho /*
69328c506b8Sjruoho * Only error is underflow, and this indicates
69428c506b8Sjruoho * a missing or null operand!
69528c506b8Sjruoho */
69628c506b8Sjruoho ACPI_EXCEPTION ((AE_INFO, Status,
69728c506b8Sjruoho "Missing or null operand"));
69828c506b8Sjruoho return_ACPI_STATUS (Status);
69928c506b8Sjruoho }
70028c506b8Sjruoho }
70128c506b8Sjruoho else
70228c506b8Sjruoho {
70328c506b8Sjruoho /* Create an ACPI_INTERNAL_OBJECT for the argument */
70428c506b8Sjruoho
70528c506b8Sjruoho ObjDesc = AcpiUtCreateInternalObject (OpInfo->ObjectType);
70628c506b8Sjruoho if (!ObjDesc)
70728c506b8Sjruoho {
70828c506b8Sjruoho return_ACPI_STATUS (AE_NO_MEMORY);
70928c506b8Sjruoho }
71028c506b8Sjruoho
71128c506b8Sjruoho /* Initialize the new object */
71228c506b8Sjruoho
71328c506b8Sjruoho Status = AcpiDsInitObjectFromOp (
71428c506b8Sjruoho WalkState, Arg, Opcode, &ObjDesc);
71528c506b8Sjruoho if (ACPI_FAILURE (Status))
71628c506b8Sjruoho {
71728c506b8Sjruoho AcpiUtDeleteObjectDesc (ObjDesc);
71828c506b8Sjruoho return_ACPI_STATUS (Status);
71928c506b8Sjruoho }
72028c506b8Sjruoho }
72128c506b8Sjruoho
72228c506b8Sjruoho /* Put the operand object on the object stack */
72328c506b8Sjruoho
72428c506b8Sjruoho Status = AcpiDsObjStackPush (ObjDesc, WalkState);
72528c506b8Sjruoho if (ACPI_FAILURE (Status))
72628c506b8Sjruoho {
72728c506b8Sjruoho return_ACPI_STATUS (Status);
72828c506b8Sjruoho }
72928c506b8Sjruoho
73081bd9c9cSchristos AcpiDbDisplayArgumentObject (ObjDesc, WalkState);
73128c506b8Sjruoho }
73228c506b8Sjruoho
73328c506b8Sjruoho return_ACPI_STATUS (AE_OK);
73428c506b8Sjruoho }
73528c506b8Sjruoho
73628c506b8Sjruoho
73728c506b8Sjruoho /*******************************************************************************
73828c506b8Sjruoho *
73928c506b8Sjruoho * FUNCTION: AcpiDsCreateOperands
74028c506b8Sjruoho *
74128c506b8Sjruoho * PARAMETERS: WalkState - Current state
74228c506b8Sjruoho * FirstArg - First argument of a parser argument tree
74328c506b8Sjruoho *
74428c506b8Sjruoho * RETURN: Status
74528c506b8Sjruoho *
74628c506b8Sjruoho * DESCRIPTION: Convert an operator's arguments from a parse tree format to
74728c506b8Sjruoho * namespace objects and place those argument object on the object
74828c506b8Sjruoho * stack in preparation for evaluation by the interpreter.
74928c506b8Sjruoho *
75028c506b8Sjruoho ******************************************************************************/
75128c506b8Sjruoho
75228c506b8Sjruoho ACPI_STATUS
AcpiDsCreateOperands(ACPI_WALK_STATE * WalkState,ACPI_PARSE_OBJECT * FirstArg)75328c506b8Sjruoho AcpiDsCreateOperands (
75428c506b8Sjruoho ACPI_WALK_STATE *WalkState,
75528c506b8Sjruoho ACPI_PARSE_OBJECT *FirstArg)
75628c506b8Sjruoho {
75728c506b8Sjruoho ACPI_STATUS Status = AE_OK;
75828c506b8Sjruoho ACPI_PARSE_OBJECT *Arg;
75928c506b8Sjruoho ACPI_PARSE_OBJECT *Arguments[ACPI_OBJ_NUM_OPERANDS];
76028c506b8Sjruoho UINT32 ArgCount = 0;
76128c506b8Sjruoho UINT32 Index = WalkState->NumOperands;
76228c506b8Sjruoho UINT32 i;
76328c506b8Sjruoho
76428c506b8Sjruoho
76528c506b8Sjruoho ACPI_FUNCTION_TRACE_PTR (DsCreateOperands, FirstArg);
76628c506b8Sjruoho
76728c506b8Sjruoho
76828c506b8Sjruoho /* Get all arguments in the list */
76928c506b8Sjruoho
77028c506b8Sjruoho Arg = FirstArg;
77128c506b8Sjruoho while (Arg)
77228c506b8Sjruoho {
77328c506b8Sjruoho if (Index >= ACPI_OBJ_NUM_OPERANDS)
77428c506b8Sjruoho {
77528c506b8Sjruoho return_ACPI_STATUS (AE_BAD_DATA);
77628c506b8Sjruoho }
77728c506b8Sjruoho
77828c506b8Sjruoho Arguments[Index] = Arg;
77928c506b8Sjruoho WalkState->Operands [Index] = NULL;
78028c506b8Sjruoho
78128c506b8Sjruoho /* Move on to next argument, if any */
78228c506b8Sjruoho
78328c506b8Sjruoho Arg = Arg->Common.Next;
78428c506b8Sjruoho ArgCount++;
78528c506b8Sjruoho Index++;
78628c506b8Sjruoho }
78728c506b8Sjruoho
788ff4a156dSchristos ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
789ff4a156dSchristos "NumOperands %d, ArgCount %d, Index %d\n",
790ff4a156dSchristos WalkState->NumOperands, ArgCount, Index));
791ff4a156dSchristos
792ff4a156dSchristos /* Create the interpreter arguments, in reverse order */
793ff4a156dSchristos
79428c506b8Sjruoho Index--;
79528c506b8Sjruoho for (i = 0; i < ArgCount; i++)
79628c506b8Sjruoho {
79728c506b8Sjruoho Arg = Arguments[Index];
79828c506b8Sjruoho WalkState->OperandIndex = (UINT8) Index;
79928c506b8Sjruoho
80028c506b8Sjruoho Status = AcpiDsCreateOperand (WalkState, Arg, Index);
80128c506b8Sjruoho if (ACPI_FAILURE (Status))
80228c506b8Sjruoho {
80328c506b8Sjruoho goto Cleanup;
80428c506b8Sjruoho }
80528c506b8Sjruoho
806ff4a156dSchristos ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
807ff4a156dSchristos "Created Arg #%u (%p) %u args total\n",
808ff4a156dSchristos Index, Arg, ArgCount));
80928c506b8Sjruoho Index--;
81028c506b8Sjruoho }
81128c506b8Sjruoho
81228c506b8Sjruoho return_ACPI_STATUS (Status);
81328c506b8Sjruoho
81428c506b8Sjruoho
81528c506b8Sjruoho Cleanup:
81628c506b8Sjruoho /*
81728c506b8Sjruoho * We must undo everything done above; meaning that we must
81828c506b8Sjruoho * pop everything off of the operand stack and delete those
81928c506b8Sjruoho * objects
82028c506b8Sjruoho */
82128c506b8Sjruoho AcpiDsObjStackPopAndDelete (ArgCount, WalkState);
82228c506b8Sjruoho
82328c506b8Sjruoho ACPI_EXCEPTION ((AE_INFO, Status, "While creating Arg %u", Index));
82428c506b8Sjruoho return_ACPI_STATUS (Status);
82528c506b8Sjruoho }
82628c506b8Sjruoho
82728c506b8Sjruoho
82828c506b8Sjruoho /*****************************************************************************
82928c506b8Sjruoho *
83028c506b8Sjruoho * FUNCTION: AcpiDsEvaluateNamePath
83128c506b8Sjruoho *
83228c506b8Sjruoho * PARAMETERS: WalkState - Current state of the parse tree walk,
83328c506b8Sjruoho * the opcode of current operation should be
83428c506b8Sjruoho * AML_INT_NAMEPATH_OP
83528c506b8Sjruoho *
83628c506b8Sjruoho * RETURN: Status
83728c506b8Sjruoho *
83828c506b8Sjruoho * DESCRIPTION: Translate the -NamePath- parse tree object to the equivalent
83928c506b8Sjruoho * interpreter object, convert it to value, if needed, duplicate
84028c506b8Sjruoho * it, if needed, and push it onto the current result stack.
84128c506b8Sjruoho *
84228c506b8Sjruoho ****************************************************************************/
84328c506b8Sjruoho
84428c506b8Sjruoho ACPI_STATUS
AcpiDsEvaluateNamePath(ACPI_WALK_STATE * WalkState)84528c506b8Sjruoho AcpiDsEvaluateNamePath (
84628c506b8Sjruoho ACPI_WALK_STATE *WalkState)
84728c506b8Sjruoho {
84828c506b8Sjruoho ACPI_STATUS Status = AE_OK;
84928c506b8Sjruoho ACPI_PARSE_OBJECT *Op = WalkState->Op;
85028c506b8Sjruoho ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0];
85128c506b8Sjruoho ACPI_OPERAND_OBJECT *NewObjDesc;
85228c506b8Sjruoho UINT8 Type;
85328c506b8Sjruoho
85428c506b8Sjruoho
85528c506b8Sjruoho ACPI_FUNCTION_TRACE_PTR (DsEvaluateNamePath, WalkState);
85628c506b8Sjruoho
85728c506b8Sjruoho
85828c506b8Sjruoho if (!Op->Common.Parent)
85928c506b8Sjruoho {
86028c506b8Sjruoho /* This happens after certain exception processing */
86128c506b8Sjruoho
86228c506b8Sjruoho goto Exit;
86328c506b8Sjruoho }
86428c506b8Sjruoho
86528c506b8Sjruoho if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
8668f1e17bdSchristos (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP) ||
86728c506b8Sjruoho (Op->Common.Parent->Common.AmlOpcode == AML_REF_OF_OP))
86828c506b8Sjruoho {
86928c506b8Sjruoho /* TBD: Should we specify this feature as a bit of OpInfo->Flags of these opcodes? */
87028c506b8Sjruoho
87128c506b8Sjruoho goto Exit;
87228c506b8Sjruoho }
87328c506b8Sjruoho
87428c506b8Sjruoho Status = AcpiDsCreateOperand (WalkState, Op, 0);
87528c506b8Sjruoho if (ACPI_FAILURE (Status))
87628c506b8Sjruoho {
87728c506b8Sjruoho goto Exit;
87828c506b8Sjruoho }
87928c506b8Sjruoho
88028c506b8Sjruoho if (Op->Common.Flags & ACPI_PARSEOP_TARGET)
88128c506b8Sjruoho {
88228c506b8Sjruoho NewObjDesc = *Operand;
88328c506b8Sjruoho goto PushResult;
88428c506b8Sjruoho }
88528c506b8Sjruoho
88628c506b8Sjruoho Type = (*Operand)->Common.Type;
88728c506b8Sjruoho
88828c506b8Sjruoho Status = AcpiExResolveToValue (Operand, WalkState);
88928c506b8Sjruoho if (ACPI_FAILURE (Status))
89028c506b8Sjruoho {
89128c506b8Sjruoho goto Exit;
89228c506b8Sjruoho }
89328c506b8Sjruoho
89428c506b8Sjruoho if (Type == ACPI_TYPE_INTEGER)
89528c506b8Sjruoho {
89628c506b8Sjruoho /* It was incremented by AcpiExResolveToValue */
89728c506b8Sjruoho
89828c506b8Sjruoho AcpiUtRemoveReference (*Operand);
89928c506b8Sjruoho
90081bd9c9cSchristos Status = AcpiUtCopyIobjectToIobject (
90181bd9c9cSchristos *Operand, &NewObjDesc, WalkState);
90228c506b8Sjruoho if (ACPI_FAILURE (Status))
90328c506b8Sjruoho {
90428c506b8Sjruoho goto Exit;
90528c506b8Sjruoho }
90628c506b8Sjruoho }
90728c506b8Sjruoho else
90828c506b8Sjruoho {
90928c506b8Sjruoho /*
91028c506b8Sjruoho * The object either was anew created or is
91128c506b8Sjruoho * a Namespace node - don't decrement it.
91228c506b8Sjruoho */
91328c506b8Sjruoho NewObjDesc = *Operand;
91428c506b8Sjruoho }
91528c506b8Sjruoho
91628c506b8Sjruoho /* Cleanup for name-path operand */
91728c506b8Sjruoho
91828c506b8Sjruoho Status = AcpiDsObjStackPop (1, WalkState);
91928c506b8Sjruoho if (ACPI_FAILURE (Status))
92028c506b8Sjruoho {
92128c506b8Sjruoho WalkState->ResultObj = NewObjDesc;
92228c506b8Sjruoho goto Exit;
92328c506b8Sjruoho }
92428c506b8Sjruoho
92528c506b8Sjruoho PushResult:
92628c506b8Sjruoho
92728c506b8Sjruoho WalkState->ResultObj = NewObjDesc;
92828c506b8Sjruoho
92928c506b8Sjruoho Status = AcpiDsResultPush (WalkState->ResultObj, WalkState);
93028c506b8Sjruoho if (ACPI_SUCCESS (Status))
93128c506b8Sjruoho {
93228c506b8Sjruoho /* Force to take it from stack */
93328c506b8Sjruoho
93428c506b8Sjruoho Op->Common.Flags |= ACPI_PARSEOP_IN_STACK;
93528c506b8Sjruoho }
93628c506b8Sjruoho
93728c506b8Sjruoho Exit:
93828c506b8Sjruoho
93928c506b8Sjruoho return_ACPI_STATUS (Status);
94028c506b8Sjruoho }
941