dsutils.c revision 281687
11539Srgrimes/*******************************************************************************
21539Srgrimes *
31539Srgrimes * Module Name: dsutils - Dispatcher utilities
41539Srgrimes *
51539Srgrimes ******************************************************************************/
61539Srgrimes
71539Srgrimes/*
81539Srgrimes * Copyright (C) 2000 - 2015, Intel Corp.
91539Srgrimes * All rights reserved.
101539Srgrimes *
111539Srgrimes * Redistribution and use in source and binary forms, with or without
121539Srgrimes * modification, are permitted provided that the following conditions
131539Srgrimes * are met:
141539Srgrimes * 1. Redistributions of source code must retain the above copyright
151539Srgrimes *    notice, this list of conditions, and the following disclaimer,
161539Srgrimes *    without modification.
171539Srgrimes * 2. Redistributions in binary form must reproduce at minimum a disclaimer
181539Srgrimes *    substantially similar to the "NO WARRANTY" disclaimer below
191539Srgrimes *    ("Disclaimer") and any redistribution must be conditioned upon
201539Srgrimes *    including a substantially similar Disclaimer requirement for further
211539Srgrimes *    binary redistribution.
221539Srgrimes * 3. Neither the names of the above-listed copyright holders nor the names
231539Srgrimes *    of any contributors may be used to endorse or promote products derived
241539Srgrimes *    from this software without specific prior written permission.
251539Srgrimes *
261539Srgrimes * Alternatively, this software may be distributed under the terms of the
271539Srgrimes * GNU General Public License ("GPL") version 2 as published by the Free
281539Srgrimes * Software Foundation.
291539Srgrimes *
301539Srgrimes * NO WARRANTY
311539Srgrimes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
321539Srgrimes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
331539Srgrimes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
341539Srgrimes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
351539Srgrimes * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
361539Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
371539Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
381539Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
391539Srgrimes * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
401539Srgrimes * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
411539Srgrimes * POSSIBILITY OF SUCH DAMAGES.
4254746Sphantom */
431539Srgrimes
441539Srgrimes#include <contrib/dev/acpica/include/acpi.h>
457655Sbde#include <contrib/dev/acpica/include/accommon.h>
467655Sbde#include <contrib/dev/acpica/include/acparser.h>
471539Srgrimes#include <contrib/dev/acpica/include/amlcode.h>
487655Sbde#include <contrib/dev/acpica/include/acdispat.h>
497655Sbde#include <contrib/dev/acpica/include/acinterp.h>
507655Sbde#include <contrib/dev/acpica/include/acnamesp.h>
517655Sbde#include <contrib/dev/acpica/include/acdebug.h>
521539Srgrimes
531539Srgrimes#define _COMPONENT          ACPI_DISPATCHER
5457035Sobrien        ACPI_MODULE_NAME    ("dsutils")
5557035Sobrien
5657035Sobrien
5757035Sobrien/*******************************************************************************
5857035Sobrien *
5957035Sobrien * FUNCTION:    AcpiDsClearImplicitReturn
6057035Sobrien *
6157035Sobrien * PARAMETERS:  WalkState           - Current State
6257035Sobrien *
6357035Sobrien * RETURN:      None.
6457035Sobrien *
6557035Sobrien * DESCRIPTION: Clear and remove a reference on an implicit return value. Used
6657035Sobrien *              to delete "stale" return values (if enabled, the return value
6757035Sobrien *              from every operator is saved at least momentarily, in case the
68101984Skeichii *              parent method exits.)
69101984Skeichii *
70101984Skeichii ******************************************************************************/
71101984Skeichii
72101984Skeichiivoid
73101984SkeichiiAcpiDsClearImplicitReturn (
741539Srgrimes    ACPI_WALK_STATE         *WalkState)
757655Sbde{
7693032Simp    ACPI_FUNCTION_NAME (DsClearImplicitReturn);
7793032Simp
7893032Simp
7993032Simp    /*
8093032Simp     * Slack must be enabled for this feature
8193032Simp     */
8293032Simp    if (!AcpiGbl_EnableInterpreterSlack)
8393032Simp    {
8493032Simp        return;
8593032Simp    }
8693032Simp
8793032Simp    if (WalkState->ImplicitReturnObj)
8893032Simp    {
891539Srgrimes        /*
901539Srgrimes         * Delete any "stale" implicit return. However, in
9193032Simp         * complex statements, the implicit return value can be
9293032Simp         * bubbled up several levels.
9393032Simp         */
9493032Simp        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
9593032Simp            "Removing reference on stale implicit return obj %p\n",
9693032Simp            WalkState->ImplicitReturnObj));
9793032Simp
9893032Simp        AcpiUtRemoveReference (WalkState->ImplicitReturnObj);
9993032Simp        WalkState->ImplicitReturnObj = NULL;
10093032Simp    }
1017655Sbde}
1027655Sbde
1037655Sbde
10457035Sobrien#ifndef ACPI_NO_METHOD_EXECUTION
10557035Sobrien/*******************************************************************************
10657035Sobrien *
10757035Sobrien * FUNCTION:    AcpiDsDoImplicitReturn
10857035Sobrien *
10957035Sobrien * PARAMETERS:  ReturnDesc          - The return value
11057035Sobrien *              WalkState           - Current State
11157035Sobrien *              AddReference        - True if a reference should be added to the
11257035Sobrien *                                    return object
11357035Sobrien *
11457035Sobrien * RETURN:      TRUE if implicit return enabled, FALSE otherwise
1157655Sbde *
1167655Sbde * DESCRIPTION: Implements the optional "implicit return".  We save the result
1177655Sbde *              of every ASL operator and control method invocation in case the
1187655Sbde *              parent method exit. Before storing a new return value, we
11954746Sphantom *              delete the previous return value.
1207655Sbde *
12157035Sobrien ******************************************************************************/
12257035Sobrien
12357035SobrienBOOLEAN
12457035SobrienAcpiDsDoImplicitReturn (
12557035Sobrien    ACPI_OPERAND_OBJECT     *ReturnDesc,
1267655Sbde    ACPI_WALK_STATE         *WalkState,
12757035Sobrien    BOOLEAN                 AddReference)
12854746Sphantom{
1291539Srgrimes    ACPI_FUNCTION_NAME (DsDoImplicitReturn);
1301539Srgrimes
13115483Sbde
1321539Srgrimes    /*
13393032Simp     * Slack must be enabled for this feature, and we must
13493032Simp     * have a valid return object
13593032Simp     */
1361539Srgrimes    if ((!AcpiGbl_EnableInterpreterSlack) ||
1371539Srgrimes        (!ReturnDesc))
1381539Srgrimes    {
1397655Sbde        return (FALSE);
1407655Sbde    }
1411539Srgrimes
1427655Sbde    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
1437655Sbde            "Result %p will be implicitly returned; Prev=%p\n",
1447655Sbde            ReturnDesc,
1457655Sbde            WalkState->ImplicitReturnObj));
1461539Srgrimes
1471539Srgrimes    /*
1487655Sbde     * Delete any "stale" implicit return value first. However, in
1497655Sbde     * complex statements, the implicit return value can be
1507655Sbde     * bubbled up several levels, so we don't clear the value if it
1517655Sbde     * is the same as the ReturnDesc.
1527655Sbde     */
1531539Srgrimes    if (WalkState->ImplicitReturnObj)
15429883Sache    {
1551539Srgrimes        if (WalkState->ImplicitReturnObj == ReturnDesc)
15629855Sache        {
15729855Sache            return (TRUE);
1581539Srgrimes        }
1591539Srgrimes        AcpiDsClearImplicitReturn (WalkState);
1601539Srgrimes    }
16190231Sbbraun
16290231Sbbraun    /* Save the implicit return value, add a reference if requested */
16390231Sbbraun
16490231Sbbraun    WalkState->ImplicitReturnObj = ReturnDesc;
16590231Sbbraun    if (AddReference)
16690231Sbbraun    {
16715483Sbde        AcpiUtAddReference (ReturnDesc);
1681539Srgrimes    }
16912028Sache
17029883Sache    return (TRUE);
1711539Srgrimes}
1721539Srgrimes
17315483Sbde
17415483Sbde/*******************************************************************************
1751539Srgrimes *
17614813Sache * FUNCTION:    AcpiDsIsResultUsed
17712028Sache *
1781539Srgrimes * PARAMETERS:  Op                  - Current Op
1791539Srgrimes *              WalkState           - Current State
18015483Sbde *
18115483Sbde * RETURN:      TRUE if result is used, FALSE otherwise
1821539Srgrimes *
18314813Sache * DESCRIPTION: Check if a result object will be used by the parent
18412028Sache *
1851539Srgrimes ******************************************************************************/
1861539Srgrimes
1877655SbdeBOOLEAN
1881539SrgrimesAcpiDsIsResultUsed (
1891539Srgrimes    ACPI_PARSE_OBJECT       *Op,
19093032Simp    ACPI_WALK_STATE         *WalkState)
19193032Simp{
19293032Simp    const ACPI_OPCODE_INFO  *ParentInfo;
19393032Simp
19493032Simp    ACPI_FUNCTION_TRACE_PTR (DsIsResultUsed, Op);
1951539Srgrimes
1967655Sbde
1971539Srgrimes    /* Must have both an Op and a Result Object */
1981539Srgrimes
199    if (!Op)
200    {
201        ACPI_ERROR ((AE_INFO, "Null Op"));
202        return_UINT8 (TRUE);
203    }
204
205    /*
206     * We know that this operator is not a
207     * Return() operator (would not come here.) The following code is the
208     * optional support for a so-called "implicit return". Some AML code
209     * assumes that the last value of the method is "implicitly" returned
210     * to the caller. Just save the last result as the return value.
211     * NOTE: this is optional because the ASL language does not actually
212     * support this behavior.
213     */
214    (void) AcpiDsDoImplicitReturn (WalkState->ResultObj, WalkState, TRUE);
215
216    /*
217     * Now determine if the parent will use the result
218     *
219     * If there is no parent, or the parent is a ScopeOp, we are executing
220     * at the method level. An executing method typically has no parent,
221     * since each method is parsed separately. A method invoked externally
222     * via ExecuteControlMethod has a ScopeOp as the parent.
223     */
224    if ((!Op->Common.Parent) ||
225        (Op->Common.Parent->Common.AmlOpcode == AML_SCOPE_OP))
226    {
227        /* No parent, the return value cannot possibly be used */
228
229        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
230            "At Method level, result of [%s] not used\n",
231            AcpiPsGetOpcodeName (Op->Common.AmlOpcode)));
232        return_UINT8 (FALSE);
233    }
234
235    /* Get info on the parent. The RootOp is AML_SCOPE */
236
237    ParentInfo = AcpiPsGetOpcodeInfo (Op->Common.Parent->Common.AmlOpcode);
238    if (ParentInfo->Class == AML_CLASS_UNKNOWN)
239    {
240        ACPI_ERROR ((AE_INFO,
241            "Unknown parent opcode Op=%p", Op));
242        return_UINT8 (FALSE);
243    }
244
245    /*
246     * Decide what to do with the result based on the parent. If
247     * the parent opcode will not use the result, delete the object.
248     * Otherwise leave it as is, it will be deleted when it is used
249     * as an operand later.
250     */
251    switch (ParentInfo->Class)
252    {
253    case AML_CLASS_CONTROL:
254
255        switch (Op->Common.Parent->Common.AmlOpcode)
256        {
257        case AML_RETURN_OP:
258
259            /* Never delete the return value associated with a return opcode */
260
261            goto ResultUsed;
262
263        case AML_IF_OP:
264        case AML_WHILE_OP:
265            /*
266             * If we are executing the predicate AND this is the predicate op,
267             * we will use the return value
268             */
269            if ((WalkState->ControlState->Common.State == ACPI_CONTROL_PREDICATE_EXECUTING) &&
270                (WalkState->ControlState->Control.PredicateOp == Op))
271            {
272                goto ResultUsed;
273            }
274            break;
275
276        default:
277
278            /* Ignore other control opcodes */
279
280            break;
281        }
282
283        /* The general control opcode returns no result */
284
285        goto ResultNotUsed;
286
287    case AML_CLASS_CREATE:
288        /*
289         * These opcodes allow TermArg(s) as operands and therefore
290         * the operands can be method calls. The result is used.
291         */
292        goto ResultUsed;
293
294    case AML_CLASS_NAMED_OBJECT:
295
296        if ((Op->Common.Parent->Common.AmlOpcode == AML_REGION_OP)       ||
297            (Op->Common.Parent->Common.AmlOpcode == AML_DATA_REGION_OP)  ||
298            (Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP)      ||
299            (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP)  ||
300            (Op->Common.Parent->Common.AmlOpcode == AML_BUFFER_OP)       ||
301            (Op->Common.Parent->Common.AmlOpcode == AML_INT_EVAL_SUBTREE_OP) ||
302            (Op->Common.Parent->Common.AmlOpcode == AML_BANK_FIELD_OP))
303        {
304            /*
305             * These opcodes allow TermArg(s) as operands and therefore
306             * the operands can be method calls. The result is used.
307             */
308            goto ResultUsed;
309        }
310
311        goto ResultNotUsed;
312
313    default:
314        /*
315         * In all other cases. the parent will actually use the return
316         * object, so keep it.
317         */
318        goto ResultUsed;
319    }
320
321
322ResultUsed:
323    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
324        "Result of [%s] used by Parent [%s] Op=%p\n",
325        AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
326        AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op));
327
328    return_UINT8 (TRUE);
329
330
331ResultNotUsed:
332    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
333        "Result of [%s] not used by Parent [%s] Op=%p\n",
334        AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
335        AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op));
336
337    return_UINT8 (FALSE);
338}
339
340
341/*******************************************************************************
342 *
343 * FUNCTION:    AcpiDsDeleteResultIfNotUsed
344 *
345 * PARAMETERS:  Op              - Current parse Op
346 *              ResultObj       - Result of the operation
347 *              WalkState       - Current state
348 *
349 * RETURN:      Status
350 *
351 * DESCRIPTION: Used after interpretation of an opcode. If there is an internal
352 *              result descriptor, check if the parent opcode will actually use
353 *              this result. If not, delete the result now so that it will
354 *              not become orphaned.
355 *
356 ******************************************************************************/
357
358void
359AcpiDsDeleteResultIfNotUsed (
360    ACPI_PARSE_OBJECT       *Op,
361    ACPI_OPERAND_OBJECT     *ResultObj,
362    ACPI_WALK_STATE         *WalkState)
363{
364    ACPI_OPERAND_OBJECT     *ObjDesc;
365    ACPI_STATUS             Status;
366
367
368    ACPI_FUNCTION_TRACE_PTR (DsDeleteResultIfNotUsed, ResultObj);
369
370
371    if (!Op)
372    {
373        ACPI_ERROR ((AE_INFO, "Null Op"));
374        return_VOID;
375    }
376
377    if (!ResultObj)
378    {
379        return_VOID;
380    }
381
382    if (!AcpiDsIsResultUsed (Op, WalkState))
383    {
384        /* Must pop the result stack (ObjDesc should be equal to ResultObj) */
385
386        Status = AcpiDsResultPop (&ObjDesc, WalkState);
387        if (ACPI_SUCCESS (Status))
388        {
389            AcpiUtRemoveReference (ResultObj);
390        }
391    }
392
393    return_VOID;
394}
395
396
397/*******************************************************************************
398 *
399 * FUNCTION:    AcpiDsResolveOperands
400 *
401 * PARAMETERS:  WalkState           - Current walk state with operands on stack
402 *
403 * RETURN:      Status
404 *
405 * DESCRIPTION: Resolve all operands to their values. Used to prepare
406 *              arguments to a control method invocation (a call from one
407 *              method to another.)
408 *
409 ******************************************************************************/
410
411ACPI_STATUS
412AcpiDsResolveOperands (
413    ACPI_WALK_STATE         *WalkState)
414{
415    UINT32                  i;
416    ACPI_STATUS             Status = AE_OK;
417
418
419    ACPI_FUNCTION_TRACE_PTR (DsResolveOperands, WalkState);
420
421
422    /*
423     * Attempt to resolve each of the valid operands
424     * Method arguments are passed by reference, not by value. This means
425     * that the actual objects are passed, not copies of the objects.
426     */
427    for (i = 0; i < WalkState->NumOperands; i++)
428    {
429        Status = AcpiExResolveToValue (&WalkState->Operands[i], WalkState);
430        if (ACPI_FAILURE (Status))
431        {
432            break;
433        }
434    }
435
436    return_ACPI_STATUS (Status);
437}
438
439
440/*******************************************************************************
441 *
442 * FUNCTION:    AcpiDsClearOperands
443 *
444 * PARAMETERS:  WalkState           - Current walk state with operands on stack
445 *
446 * RETURN:      None
447 *
448 * DESCRIPTION: Clear all operands on the current walk state operand stack.
449 *
450 ******************************************************************************/
451
452void
453AcpiDsClearOperands (
454    ACPI_WALK_STATE         *WalkState)
455{
456    UINT32                  i;
457
458
459    ACPI_FUNCTION_TRACE_PTR (DsClearOperands, WalkState);
460
461
462    /* Remove a reference on each operand on the stack */
463
464    for (i = 0; i < WalkState->NumOperands; i++)
465    {
466        /*
467         * Remove a reference to all operands, including both
468         * "Arguments" and "Targets".
469         */
470        AcpiUtRemoveReference (WalkState->Operands[i]);
471        WalkState->Operands[i] = NULL;
472    }
473
474    WalkState->NumOperands = 0;
475    return_VOID;
476}
477#endif
478
479
480/*******************************************************************************
481 *
482 * FUNCTION:    AcpiDsCreateOperand
483 *
484 * PARAMETERS:  WalkState       - Current walk state
485 *              Arg             - Parse object for the argument
486 *              ArgIndex        - Which argument (zero based)
487 *
488 * RETURN:      Status
489 *
490 * DESCRIPTION: Translate a parse tree object that is an argument to an AML
491 *              opcode to the equivalent interpreter object. This may include
492 *              looking up a name or entering a new name into the internal
493 *              namespace.
494 *
495 ******************************************************************************/
496
497ACPI_STATUS
498AcpiDsCreateOperand (
499    ACPI_WALK_STATE         *WalkState,
500    ACPI_PARSE_OBJECT       *Arg,
501    UINT32                  ArgIndex)
502{
503    ACPI_STATUS             Status = AE_OK;
504    char                    *NameString;
505    UINT32                  NameLength;
506    ACPI_OPERAND_OBJECT     *ObjDesc;
507    ACPI_PARSE_OBJECT       *ParentOp;
508    UINT16                  Opcode;
509    ACPI_INTERPRETER_MODE   InterpreterMode;
510    const ACPI_OPCODE_INFO  *OpInfo;
511
512
513    ACPI_FUNCTION_TRACE_PTR (DsCreateOperand, Arg);
514
515
516    /* A valid name must be looked up in the namespace */
517
518    if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
519        (Arg->Common.Value.String) &&
520        !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
521    {
522        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", Arg));
523
524        /* Get the entire name string from the AML stream */
525
526        Status = AcpiExGetNameString (ACPI_TYPE_ANY, Arg->Common.Value.Buffer,
527                        &NameString, &NameLength);
528
529        if (ACPI_FAILURE (Status))
530        {
531            return_ACPI_STATUS (Status);
532        }
533
534        /* All prefixes have been handled, and the name is in NameString */
535
536        /*
537         * Special handling for BufferField declarations. This is a deferred
538         * opcode that unfortunately defines the field name as the last
539         * parameter instead of the first. We get here when we are performing
540         * the deferred execution, so the actual name of the field is already
541         * in the namespace. We don't want to attempt to look it up again
542         * because we may be executing in a different scope than where the
543         * actual opcode exists.
544         */
545        if ((WalkState->DeferredNode) &&
546            (WalkState->DeferredNode->Type == ACPI_TYPE_BUFFER_FIELD) &&
547            (ArgIndex == (UINT32) ((WalkState->Opcode == AML_CREATE_FIELD_OP) ? 3 : 2)))
548        {
549            ObjDesc = ACPI_CAST_PTR (
550                        ACPI_OPERAND_OBJECT, WalkState->DeferredNode);
551            Status = AE_OK;
552        }
553        else    /* All other opcodes */
554        {
555            /*
556             * Differentiate between a namespace "create" operation
557             * versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
558             * IMODE_EXECUTE) in order to support the creation of
559             * namespace objects during the execution of control methods.
560             */
561            ParentOp = Arg->Common.Parent;
562            OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode);
563            if ((OpInfo->Flags & AML_NSNODE) &&
564                (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) &&
565                (ParentOp->Common.AmlOpcode != AML_REGION_OP) &&
566                (ParentOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP))
567            {
568                /* Enter name into namespace if not found */
569
570                InterpreterMode = ACPI_IMODE_LOAD_PASS2;
571            }
572            else
573            {
574                /* Return a failure if name not found */
575
576                InterpreterMode = ACPI_IMODE_EXECUTE;
577            }
578
579            Status = AcpiNsLookup (WalkState->ScopeInfo, NameString,
580                        ACPI_TYPE_ANY, InterpreterMode,
581                        ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
582                        WalkState,
583                        ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &ObjDesc));
584            /*
585             * The only case where we pass through (ignore) a NOT_FOUND
586             * error is for the CondRefOf opcode.
587             */
588            if (Status == AE_NOT_FOUND)
589            {
590                if (ParentOp->Common.AmlOpcode == AML_COND_REF_OF_OP)
591                {
592                    /*
593                     * For the Conditional Reference op, it's OK if
594                     * the name is not found;  We just need a way to
595                     * indicate this to the interpreter, set the
596                     * object to the root
597                     */
598                    ObjDesc = ACPI_CAST_PTR (
599                                ACPI_OPERAND_OBJECT, AcpiGbl_RootNode);
600                    Status = AE_OK;
601                }
602                else if (ParentOp->Common.AmlOpcode == AML_EXTERNAL_OP)
603                {
604                    /* TBD: May only be temporary */
605
606                    ObjDesc = AcpiUtCreateStringObject ((ACPI_SIZE) NameLength);
607
608                    ACPI_STRNCPY (ObjDesc->String.Pointer, NameString, NameLength);
609                    Status = AE_OK;
610                }
611                else
612                {
613                    /*
614                     * We just plain didn't find it -- which is a
615                     * very serious error at this point
616                     */
617                    Status = AE_AML_NAME_NOT_FOUND;
618                }
619            }
620
621            if (ACPI_FAILURE (Status))
622            {
623                ACPI_ERROR_NAMESPACE (NameString, Status);
624            }
625        }
626
627        /* Free the namestring created above */
628
629        ACPI_FREE (NameString);
630
631        /* Check status from the lookup */
632
633        if (ACPI_FAILURE (Status))
634        {
635            return_ACPI_STATUS (Status);
636        }
637
638        /* Put the resulting object onto the current object stack */
639
640        Status = AcpiDsObjStackPush (ObjDesc, WalkState);
641        if (ACPI_FAILURE (Status))
642        {
643            return_ACPI_STATUS (Status);
644        }
645        ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState));
646    }
647    else
648    {
649        /* Check for null name case */
650
651        if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
652            !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
653        {
654            /*
655             * If the name is null, this means that this is an
656             * optional result parameter that was not specified
657             * in the original ASL. Create a Zero Constant for a
658             * placeholder. (Store to a constant is a Noop.)
659             */
660            Opcode = AML_ZERO_OP;       /* Has no arguments! */
661
662            ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
663                "Null namepath: Arg=%p\n", Arg));
664        }
665        else
666        {
667            Opcode = Arg->Common.AmlOpcode;
668        }
669
670        /* Get the object type of the argument */
671
672        OpInfo = AcpiPsGetOpcodeInfo (Opcode);
673        if (OpInfo->ObjectType == ACPI_TYPE_INVALID)
674        {
675            return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
676        }
677
678        if ((OpInfo->Flags & AML_HAS_RETVAL) || (Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
679        {
680            ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
681                "Argument previously created, already stacked\n"));
682
683            ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (
684                WalkState->Operands [WalkState->NumOperands - 1], WalkState));
685
686            /*
687             * Use value that was already previously returned
688             * by the evaluation of this argument
689             */
690            Status = AcpiDsResultPop (&ObjDesc, WalkState);
691            if (ACPI_FAILURE (Status))
692            {
693                /*
694                 * Only error is underflow, and this indicates
695                 * a missing or null operand!
696                 */
697                ACPI_EXCEPTION ((AE_INFO, Status,
698                    "Missing or null operand"));
699                return_ACPI_STATUS (Status);
700            }
701        }
702        else
703        {
704            /* Create an ACPI_INTERNAL_OBJECT for the argument */
705
706            ObjDesc = AcpiUtCreateInternalObject (OpInfo->ObjectType);
707            if (!ObjDesc)
708            {
709                return_ACPI_STATUS (AE_NO_MEMORY);
710            }
711
712            /* Initialize the new object */
713
714            Status = AcpiDsInitObjectFromOp (
715                        WalkState, Arg, Opcode, &ObjDesc);
716            if (ACPI_FAILURE (Status))
717            {
718                AcpiUtDeleteObjectDesc (ObjDesc);
719                return_ACPI_STATUS (Status);
720            }
721        }
722
723        /* Put the operand object on the object stack */
724
725        Status = AcpiDsObjStackPush (ObjDesc, WalkState);
726        if (ACPI_FAILURE (Status))
727        {
728            return_ACPI_STATUS (Status);
729        }
730
731        ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState));
732    }
733
734    return_ACPI_STATUS (AE_OK);
735}
736
737
738/*******************************************************************************
739 *
740 * FUNCTION:    AcpiDsCreateOperands
741 *
742 * PARAMETERS:  WalkState           - Current state
743 *              FirstArg            - First argument of a parser argument tree
744 *
745 * RETURN:      Status
746 *
747 * DESCRIPTION: Convert an operator's arguments from a parse tree format to
748 *              namespace objects and place those argument object on the object
749 *              stack in preparation for evaluation by the interpreter.
750 *
751 ******************************************************************************/
752
753ACPI_STATUS
754AcpiDsCreateOperands (
755    ACPI_WALK_STATE         *WalkState,
756    ACPI_PARSE_OBJECT       *FirstArg)
757{
758    ACPI_STATUS             Status = AE_OK;
759    ACPI_PARSE_OBJECT       *Arg;
760    ACPI_PARSE_OBJECT       *Arguments[ACPI_OBJ_NUM_OPERANDS];
761    UINT32                  ArgCount = 0;
762    UINT32                  Index = WalkState->NumOperands;
763    UINT32                  i;
764
765
766    ACPI_FUNCTION_TRACE_PTR (DsCreateOperands, FirstArg);
767
768
769    /* Get all arguments in the list */
770
771    Arg = FirstArg;
772    while (Arg)
773    {
774        if (Index >= ACPI_OBJ_NUM_OPERANDS)
775        {
776            return_ACPI_STATUS (AE_BAD_DATA);
777        }
778
779        Arguments[Index] = Arg;
780        WalkState->Operands [Index] = NULL;
781
782        /* Move on to next argument, if any */
783
784        Arg = Arg->Common.Next;
785        ArgCount++;
786        Index++;
787    }
788
789    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
790        "NumOperands %d, ArgCount %d, Index %d\n",
791        WalkState->NumOperands, ArgCount, Index));
792
793    /* Create the interpreter arguments, in reverse order */
794
795    Index--;
796    for (i = 0; i < ArgCount; i++)
797    {
798        Arg = Arguments[Index];
799        WalkState->OperandIndex = (UINT8) Index;
800
801        Status = AcpiDsCreateOperand (WalkState, Arg, Index);
802        if (ACPI_FAILURE (Status))
803        {
804            goto Cleanup;
805        }
806
807        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
808            "Created Arg #%u (%p) %u args total\n",
809            Index, Arg, ArgCount));
810        Index--;
811    }
812
813    return_ACPI_STATUS (Status);
814
815
816Cleanup:
817    /*
818     * We must undo everything done above; meaning that we must
819     * pop everything off of the operand stack and delete those
820     * objects
821     */
822    AcpiDsObjStackPopAndDelete (ArgCount, WalkState);
823
824    ACPI_EXCEPTION ((AE_INFO, Status, "While creating Arg %u", Index));
825    return_ACPI_STATUS (Status);
826}
827
828
829/*****************************************************************************
830 *
831 * FUNCTION:    AcpiDsEvaluateNamePath
832 *
833 * PARAMETERS:  WalkState       - Current state of the parse tree walk,
834 *                                the opcode of current operation should be
835 *                                AML_INT_NAMEPATH_OP
836 *
837 * RETURN:      Status
838 *
839 * DESCRIPTION: Translate the -NamePath- parse tree object to the equivalent
840 *              interpreter object, convert it to value, if needed, duplicate
841 *              it, if needed, and push it onto the current result stack.
842 *
843 ****************************************************************************/
844
845ACPI_STATUS
846AcpiDsEvaluateNamePath (
847    ACPI_WALK_STATE         *WalkState)
848{
849    ACPI_STATUS             Status = AE_OK;
850    ACPI_PARSE_OBJECT       *Op = WalkState->Op;
851    ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
852    ACPI_OPERAND_OBJECT     *NewObjDesc;
853    UINT8                   Type;
854
855
856    ACPI_FUNCTION_TRACE_PTR (DsEvaluateNamePath, WalkState);
857
858
859    if (!Op->Common.Parent)
860    {
861        /* This happens after certain exception processing */
862
863        goto Exit;
864    }
865
866    if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
867        (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP) ||
868        (Op->Common.Parent->Common.AmlOpcode == AML_REF_OF_OP))
869    {
870        /* TBD: Should we specify this feature as a bit of OpInfo->Flags of these opcodes? */
871
872        goto Exit;
873    }
874
875    Status = AcpiDsCreateOperand (WalkState, Op, 0);
876    if (ACPI_FAILURE (Status))
877    {
878        goto Exit;
879    }
880
881    if (Op->Common.Flags & ACPI_PARSEOP_TARGET)
882    {
883        NewObjDesc = *Operand;
884        goto PushResult;
885    }
886
887    Type = (*Operand)->Common.Type;
888
889    Status = AcpiExResolveToValue (Operand, WalkState);
890    if (ACPI_FAILURE (Status))
891    {
892        goto Exit;
893    }
894
895    if (Type == ACPI_TYPE_INTEGER)
896    {
897        /* It was incremented by AcpiExResolveToValue */
898
899        AcpiUtRemoveReference (*Operand);
900
901        Status = AcpiUtCopyIobjectToIobject (*Operand, &NewObjDesc, WalkState);
902        if (ACPI_FAILURE (Status))
903        {
904            goto Exit;
905        }
906    }
907    else
908    {
909        /*
910         * The object either was anew created or is
911         * a Namespace node - don't decrement it.
912         */
913        NewObjDesc = *Operand;
914    }
915
916    /* Cleanup for name-path operand */
917
918    Status = AcpiDsObjStackPop (1, WalkState);
919    if (ACPI_FAILURE (Status))
920    {
921        WalkState->ResultObj = NewObjDesc;
922        goto Exit;
923    }
924
925PushResult:
926
927    WalkState->ResultObj = NewObjDesc;
928
929    Status = AcpiDsResultPush (WalkState->ResultObj, WalkState);
930    if (ACPI_SUCCESS (Status))
931    {
932        /* Force to take it from stack */
933
934        Op->Common.Flags |= ACPI_PARSEOP_IN_STACK;
935    }
936
937Exit:
938
939    return_ACPI_STATUS (Status);
940}
941